agora inbox for [email protected]help / color / mirror / Atom feed
[PATCH v6 1/2] Clear padding in PgStat_HashKey keys 209+ messages / 2 participants [nested] [flat]
* [PATCH v6 1/2] Clear padding in PgStat_HashKey keys @ 2024-11-02 14:21 Bertrand Drouvot <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Bertrand Drouvot @ 2024-11-02 14:21 UTC (permalink / raw) PgStat_HashKey keys are currently initialized in a way that could result in random data in the padding bytes (if there was padding in PgStat_HashKey which is not the case currently). We are using sizeof(PgStat_HashKey) in pgstat_cmp_hash_key() and we compute the hash hash key in pgstat_hash_hash_key() using the PgStat_HashKey struct size as input. So, we have to ensure that no random data can be stored in the padding bytes (if any) of a PgStat_HashKey key. --- src/backend/utils/activity/pgstat.c | 3 +++ src/backend/utils/activity/pgstat_shmem.c | 18 ++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) 100.0% src/backend/utils/activity/ diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c index be48432cc3..ea8c5691e8 100644 --- a/src/backend/utils/activity/pgstat.c +++ b/src/backend/utils/activity/pgstat.c @@ -938,6 +938,9 @@ pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, uint64 objid) pgstat_prep_snapshot(); + /* clear padding */ + memset(&key, 0, sizeof(struct PgStat_HashKey)); + key.kind = kind; key.dboid = dboid; key.objid = objid; diff --git a/src/backend/utils/activity/pgstat_shmem.c b/src/backend/utils/activity/pgstat_shmem.c index a09c6fee05..c1b7ff76b1 100644 --- a/src/backend/utils/activity/pgstat_shmem.c +++ b/src/backend/utils/activity/pgstat_shmem.c @@ -432,11 +432,18 @@ PgStat_EntryRef * pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, uint64 objid, bool create, bool *created_entry) { - PgStat_HashKey key = {.kind = kind,.dboid = dboid,.objid = objid}; + PgStat_HashKey key; PgStatShared_HashEntry *shhashent; PgStatShared_Common *shheader = NULL; PgStat_EntryRef *entry_ref; + /* clear padding */ + memset(&key, 0, sizeof(struct PgStat_HashKey)); + + key.kind = kind; + key.dboid = dboid; + key.objid = objid; + /* * passing in created_entry only makes sense if we possibly could create * entry. @@ -908,10 +915,17 @@ pgstat_drop_database_and_contents(Oid dboid) bool pgstat_drop_entry(PgStat_Kind kind, Oid dboid, uint64 objid) { - PgStat_HashKey key = {.kind = kind,.dboid = dboid,.objid = objid}; + PgStat_HashKey key; PgStatShared_HashEntry *shent; bool freed = true; + /* clear padding */ + memset(&key, 0, sizeof(struct PgStat_HashKey)); + + key.kind = kind; + key.dboid = dboid; + key.objid = objid; + /* delete local reference */ if (pgStatEntryRefHash) { -- 2.34.1 --gvmrl0mfoTEJEfPE Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="v6-0002-Provide-relfilenode-statistics.patch" Content-Transfer-Encoding: 8bit ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 209+ messages in thread From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw) --- src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 5ee80c7632e..035932197a4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -40,11 +40,11 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/atomics.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/shmem.h" -#include "storage/spin.h" #include "storage/standby.h" #include "storage/subsystems.h" #include "utils/memutils.h" @@ -306,13 +306,7 @@ static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock); #define FastPathStrongLockHashPartition(hashcode) \ ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS) -typedef struct -{ - slock_t mutex; - uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; -} FastPathStrongRelationLockData; - -static FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static pg_atomic_uint32 *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); @@ -484,7 +478,8 @@ LockManagerShmemRequest(void *arg) ); ShmemRequestStruct(.name = "Fast Path Strong Relation Lock Data", - .size = sizeof(FastPathStrongRelationLockData), + .size = mul_size(sizeof(pg_atomic_uint32), + FAST_PATH_STRONG_LOCK_HASH_PARTITIONS), .ptr = (void **) (void *) &FastPathStrongRelationLocks, ); } @@ -492,7 +487,8 @@ LockManagerShmemRequest(void *arg) static void LockManagerShmemInit(void *arg) { - SpinLockInit(&FastPathStrongRelationLocks->mutex); + for (int i = 0; i < FAST_PATH_STRONG_LOCK_HASH_PARTITIONS; i++) + pg_atomic_init_u32(&FastPathStrongRelationLocks[i], 0); } /* @@ -992,11 +988,11 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * LWLockAcquire acts as a memory sequencing point, so it's safe * to assume that any strong locker whose increment to - * FastPathStrongRelationLocks->counts becomes visible after we - * test it has yet to begin to transfer fast-path locks. + * FastPathStrongRelationLocks becomes visible after we test it + * has yet to begin to transfer fast-path locks. */ LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - if (FastPathStrongRelationLocks->count[fasthashcode] != 0) + if (pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) != 0) acquired = false; else acquired = FastPathGrantRelationLock(locktag->locktag_field2, @@ -1501,11 +1497,9 @@ RemoveLocalLock(LOCALLOCK *locallock) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } if (!hash_search(LockMethodLocalHash, @@ -1834,20 +1828,9 @@ BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode) Assert(StrongLockInProgress == NULL); Assert(locallock->holdsStrongLockCount == false); - /* - * Adding to a memory location is not atomic, so we take a spinlock to - * ensure we don't collide with someone else trying to bump the count at - * the same time. - * - * XXX: It might be worth considering using an atomic fetch-and-add - * instruction here, on architectures where that is supported. - */ - - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = true; StrongLockInProgress = locallock; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -1875,12 +1858,10 @@ AbortStrongLockAcquire(void) fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode); Assert(locallock->holdsStrongLockCount == true); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); locallock->holdsStrongLockCount = false; StrongLockInProgress = NULL; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); } /* @@ -3365,10 +3346,8 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0); - FastPathStrongRelationLocks->count[fasthashcode]--; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + Assert(pg_atomic_read_u32(&FastPathStrongRelationLocks[fasthashcode]) > 0); + pg_atomic_fetch_sub_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } } @@ -4504,9 +4483,7 @@ lock_twophase_recover(FullTransactionId fxid, uint16 info, { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); - SpinLockAcquire(&FastPathStrongRelationLocks->mutex); - FastPathStrongRelationLocks->count[fasthashcode]++; - SpinLockRelease(&FastPathStrongRelationLocks->mutex); + pg_atomic_fetch_add_u32(&FastPathStrongRelationLocks[fasthashcode], 1); } LWLockRelease(partitionLock); -- 2.50.1 (Apple Git-155) --Ot5x3ffkWEuxilWO-- ^ permalink raw reply [nested|flat] 209+ messages in thread
end of thread, other threads:[~2026-07-09 20:38 UTC | newest] Thread overview: 209+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2024-11-02 14:21 [PATCH v6 1/2] Clear padding in PgStat_HashKey keys Bertrand Drouvot <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]> 2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox