agora inbox for [email protected]help / color / mirror / Atom feed
[PATCH v2 2/3] Deprecate CREATE MATERIALIZED VIEW IF NOT EXISTS 40+ messages / 2 participants [nested] [flat]
* [PATCH v2 2/3] Deprecate CREATE MATERIALIZED VIEW IF NOT EXISTS @ 2024-05-28 00:19 Erik Wienhold <[email protected]> 0 siblings, 0 replies; 40+ messages in thread From: Erik Wienhold @ 2024-05-28 00:19 UTC (permalink / raw) --- src/backend/parser/gram.y | 14 +++++++++++++ .../expected/test_extensions.out | 18 +++++++++++++++++ src/test/regress/expected/matview.out | 20 +++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index ed477806d1..b1100bdec1 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -4830,6 +4830,20 @@ CreateMatViewStmt: $8->rel->relpersistence = $2; $8->skipData = !($11); $$ = (Node *) ctas; + + if (ctas->into->rel->schemaname) + ereport(WARNING, + errmsg("IF NOT EXISTS is deprecated in materialized view creation"), + errhint("Use CREATE OR REPLACE MATERIALIZED VIEW %s.%s.", + ctas->into->rel->schemaname, + ctas->into->rel->relname), + parser_errposition(@1)); + else + ereport(WARNING, + errmsg("IF NOT EXISTS is deprecated in materialized view creation"), + errhint("Use CREATE OR REPLACE MATERIALIZED VIEW %s.", + ctas->into->rel->relname), + parser_errposition(@1)); } | CREATE OR REPLACE OptNoLog MATERIALIZED VIEW create_mv_target AS SelectStmt opt_with_data { diff --git a/src/test/modules/test_extensions/expected/test_extensions.out b/src/test/modules/test_extensions/expected/test_extensions.out index f357cc21aa..ecd453b29d 100644 --- a/src/test/modules/test_extensions/expected/test_extensions.out +++ b/src/test/modules/test_extensions/expected/test_extensions.out @@ -377,41 +377,57 @@ Objects in extension "test_ext_cor" CREATE COLLATION ext_cine_coll ( LC_COLLATE = "C", LC_CTYPE = "C" ); CREATE EXTENSION test_ext_cine; -- fail +WARNING: IF NOT EXISTS is deprecated in materialized view creation +HINT: Use CREATE OR REPLACE MATERIALIZED VIEW ext_cine_mv. ERROR: collation ext_cine_coll is not a member of extension "test_ext_cine" DETAIL: An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns. DROP COLLATION ext_cine_coll; CREATE MATERIALIZED VIEW ext_cine_mv AS SELECT 11 AS f1; CREATE EXTENSION test_ext_cine; -- fail +WARNING: IF NOT EXISTS is deprecated in materialized view creation +HINT: Use CREATE OR REPLACE MATERIALIZED VIEW ext_cine_mv. ERROR: materialized view ext_cine_mv is not a member of extension "test_ext_cine" DETAIL: An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns. DROP MATERIALIZED VIEW ext_cine_mv; CREATE FOREIGN DATA WRAPPER dummy; CREATE SERVER ext_cine_srv FOREIGN DATA WRAPPER dummy; CREATE EXTENSION test_ext_cine; -- fail +WARNING: IF NOT EXISTS is deprecated in materialized view creation +HINT: Use CREATE OR REPLACE MATERIALIZED VIEW ext_cine_mv. ERROR: server ext_cine_srv is not a member of extension "test_ext_cine" DETAIL: An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns. DROP SERVER ext_cine_srv; CREATE SCHEMA ext_cine_schema; CREATE EXTENSION test_ext_cine; -- fail +WARNING: IF NOT EXISTS is deprecated in materialized view creation +HINT: Use CREATE OR REPLACE MATERIALIZED VIEW ext_cine_mv. ERROR: schema ext_cine_schema is not a member of extension "test_ext_cine" DETAIL: An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns. DROP SCHEMA ext_cine_schema; CREATE SEQUENCE ext_cine_seq; CREATE EXTENSION test_ext_cine; -- fail +WARNING: IF NOT EXISTS is deprecated in materialized view creation +HINT: Use CREATE OR REPLACE MATERIALIZED VIEW ext_cine_mv. ERROR: sequence ext_cine_seq is not a member of extension "test_ext_cine" DETAIL: An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns. DROP SEQUENCE ext_cine_seq; CREATE TABLE ext_cine_tab1 (x int); CREATE EXTENSION test_ext_cine; -- fail +WARNING: IF NOT EXISTS is deprecated in materialized view creation +HINT: Use CREATE OR REPLACE MATERIALIZED VIEW ext_cine_mv. ERROR: table ext_cine_tab1 is not a member of extension "test_ext_cine" DETAIL: An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns. DROP TABLE ext_cine_tab1; CREATE TABLE ext_cine_tab2 AS SELECT 42 AS y; CREATE EXTENSION test_ext_cine; -- fail +WARNING: IF NOT EXISTS is deprecated in materialized view creation +HINT: Use CREATE OR REPLACE MATERIALIZED VIEW ext_cine_mv. ERROR: table ext_cine_tab2 is not a member of extension "test_ext_cine" DETAIL: An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns. DROP TABLE ext_cine_tab2; CREATE EXTENSION test_ext_cine; +WARNING: IF NOT EXISTS is deprecated in materialized view creation +HINT: Use CREATE OR REPLACE MATERIALIZED VIEW ext_cine_mv. \dx+ test_ext_cine Objects in extension "test_ext_cine" Object description @@ -433,6 +449,8 @@ Objects in extension "test_ext_cine" (14 rows) ALTER EXTENSION test_ext_cine UPDATE TO '1.1'; +WARNING: IF NOT EXISTS is deprecated in materialized view creation +HINT: Use CREATE OR REPLACE MATERIALIZED VIEW ext_cine_mv. \dx+ test_ext_cine Objects in extension "test_ext_cine" Object description diff --git a/src/test/regress/expected/matview.out b/src/test/regress/expected/matview.out index e2e2a13396..cefd0d442c 100644 --- a/src/test/regress/expected/matview.out +++ b/src/test/regress/expected/matview.out @@ -565,6 +565,10 @@ CREATE MATERIALIZED VIEW mvtest_mv_foo AS SELECT * FROM mvtest_foo_data; CREATE MATERIALIZED VIEW mvtest_mv_foo AS SELECT * FROM mvtest_foo_data; ERROR: relation "mvtest_mv_foo" already exists CREATE MATERIALIZED VIEW IF NOT EXISTS mvtest_mv_foo AS SELECT * FROM mvtest_foo_data; +WARNING: IF NOT EXISTS is deprecated in materialized view creation +LINE 1: CREATE MATERIALIZED VIEW IF NOT EXISTS mvtest_mv_foo AS SELE... + ^ +HINT: Use CREATE OR REPLACE MATERIALIZED VIEW mvtest_mv_foo. NOTICE: relation "mvtest_mv_foo" already exists, skipping CREATE UNIQUE INDEX ON mvtest_mv_foo (i); RESET ROLE; @@ -662,12 +666,20 @@ CREATE MATERIALIZED VIEW matview_ine_tab AS SELECT 1 / 0; -- error ERROR: relation "matview_ine_tab" already exists CREATE MATERIALIZED VIEW IF NOT EXISTS matview_ine_tab AS SELECT 1 / 0; -- ok +WARNING: IF NOT EXISTS is deprecated in materialized view creation +LINE 1: CREATE MATERIALIZED VIEW IF NOT EXISTS matview_ine_tab AS + ^ +HINT: Use CREATE OR REPLACE MATERIALIZED VIEW matview_ine_tab. NOTICE: relation "matview_ine_tab" already exists, skipping CREATE MATERIALIZED VIEW matview_ine_tab AS SELECT 1 / 0 WITH NO DATA; -- error ERROR: relation "matview_ine_tab" already exists CREATE MATERIALIZED VIEW IF NOT EXISTS matview_ine_tab AS SELECT 1 / 0 WITH NO DATA; -- ok +WARNING: IF NOT EXISTS is deprecated in materialized view creation +LINE 1: CREATE MATERIALIZED VIEW IF NOT EXISTS matview_ine_tab AS + ^ +HINT: Use CREATE OR REPLACE MATERIALIZED VIEW matview_ine_tab. NOTICE: relation "matview_ine_tab" already exists, skipping EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) CREATE MATERIALIZED VIEW matview_ine_tab AS @@ -676,6 +688,10 @@ ERROR: relation "matview_ine_tab" already exists EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) CREATE MATERIALIZED VIEW IF NOT EXISTS matview_ine_tab AS SELECT 1 / 0; -- ok +WARNING: IF NOT EXISTS is deprecated in materialized view creation +LINE 2: CREATE MATERIALIZED VIEW IF NOT EXISTS matview_ine_tab AS + ^ +HINT: Use CREATE OR REPLACE MATERIALIZED VIEW matview_ine_tab. NOTICE: relation "matview_ine_tab" already exists, skipping QUERY PLAN ------------ @@ -688,6 +704,10 @@ ERROR: relation "matview_ine_tab" already exists EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) CREATE MATERIALIZED VIEW IF NOT EXISTS matview_ine_tab AS SELECT 1 / 0 WITH NO DATA; -- ok +WARNING: IF NOT EXISTS is deprecated in materialized view creation +LINE 2: CREATE MATERIALIZED VIEW IF NOT EXISTS matview_ine_tab AS + ^ +HINT: Use CREATE OR REPLACE MATERIALIZED VIEW matview_ine_tab. NOTICE: relation "matview_ine_tab" already exists, skipping QUERY PLAN ------------ -- 2.45.2 --nrp556lrhtfteavd Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v2-0003-Replace-matview-WITH-OLD-DATA.patch" ^ permalink raw reply [nested|flat] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics @ 2026-07-09 20:38 Nathan Bossart <[email protected]> 0 siblings, 0 replies; 40+ 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] 40+ messages in thread
end of thread, other threads:[~2026-07-09 20:38 UTC | newest] Thread overview: 40+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2024-05-28 00:19 [PATCH v2 2/3] Deprecate CREATE MATERIALIZED VIEW IF NOT EXISTS Erik Wienhold <[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