agora inbox for pgsql-hackers@postgresql.org
help / color / mirror / Atom feedRe: Switch to multi-inserts for pg_depend
694+ messages / 4 participants
[nested] [flat]
* Re: Switch to multi-inserts for pg_depend
@ 2020-09-01 09:53 Daniel Gustafsson <daniel@yesql.se>
2020-09-03 05:35 ` Re: Switch to multi-inserts for pg_depend Michael Paquier <michael@paquier.xyz>
0 siblings, 1 reply; 694+ messages in thread
From: Daniel Gustafsson @ 2020-09-01 09:53 UTC (permalink / raw)
To: Michael Paquier <michael@paquier.xyz>; +Cc: Alvaro Herrera <alvherre@2ndquadrant.com>; Robert Haas <robertmhaas@gmail.com>; Andres Freund <andres@anarazel.de>; Postgres hackers <pgsql-hackers@lists.postgresql.org>
> On 14 Aug 2020, at 20:23, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:
> The logic to keep track number of used slots used is baroque, though -- that
> could use a lot of simplification.
What if slot_init was an integer which increments together with the loop
variable until max_slots is reached? If so, maybe it should be renamed
slot_init_count and slotCount renamed slot_stored_count to make the their use
clearer?
> On 31 Aug 2020, at 09:56, Michael Paquier <michael@paquier.xyz> wrote:
> It has been a couple of weeks, and I am not really sure what is the
> suggestion here. So I would like to move on with this patch set as
> the changes are straight-forward using the existing routines for
> object addresses by grouping all insert dependencies of the same type.
> Are there any objections?
I'm obviously biased but I think this patchset is a net win. There are more
things we can do in this space, but it's a good start.
> Attached is a rebased set, where I have added in indexing.h a unique
> definition for the hard limit of 64kB for the amount of data that can
> be inserted at once, based on the suggestion from Alvaro and Andres.
+#define MAX_CATALOG_INSERT_BYTES 65535
This name, and inclusion in a headerfile, implies that the definition is
somewhat generic as opposed to its actual use. Using MULTIINSERT rather than
INSERT in the name would clarify I reckon.
A few other comments:
+ /*
+ * Allocate the slots to use, but delay initialization until we know that
+ * they will be used.
+ */
I think this comment warrants a longer explanation on why they wont all be
used, or perhaps none of them (which is the real optimization win here).
+ ObjectAddresses *addrs_auto;
+ ObjectAddresses *addrs_normal;
It's not for this patch, but it seems a logical next step would be to be able
to record the DependencyType as well when collecting deps rather than having to
create multiple buckets.
+ /* Normal dependency from a domain to its collation. */
+ /* We know the default collation is pinned, so don't bother recording it */
It's just moved and not introduced in this patch, but shouldn't these two lines
be joined into a normal block comment?
cheers ./daniel
^ permalink raw reply [nested|flat] 694+ messages in thread
* Re: Switch to multi-inserts for pg_depend
2020-09-01 09:53 Re: Switch to multi-inserts for pg_depend Daniel Gustafsson <daniel@yesql.se>
@ 2020-09-03 05:35 ` Michael Paquier <michael@paquier.xyz>
2020-09-03 07:47 ` Re: Switch to multi-inserts for pg_depend Daniel Gustafsson <daniel@yesql.se>
2020-09-03 14:50 ` Re: Switch to multi-inserts for pg_depend Alvaro Herrera <alvherre@2ndquadrant.com>
0 siblings, 2 replies; 694+ messages in thread
From: Michael Paquier @ 2020-09-03 05:35 UTC (permalink / raw)
To: Daniel Gustafsson <daniel@yesql.se>; +Cc: Alvaro Herrera <alvherre@2ndquadrant.com>; Robert Haas <robertmhaas@gmail.com>; Andres Freund <andres@anarazel.de>; Postgres hackers <pgsql-hackers@lists.postgresql.org>
On Tue, Sep 01, 2020 at 11:53:36AM +0200, Daniel Gustafsson wrote:
> On 14 Aug 2020, at 20:23, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:
>
>> The logic to keep track number of used slots used is baroque, though -- that
>> could use a lot of simplification.
>
> What if slot_init was an integer which increments together with the loop
> variable until max_slots is reached? If so, maybe it should be renamed
> slot_init_count and slotCount renamed slot_stored_count to make the their use
> clearer?
Good idea, removing slot_init looks like a good thing for readability.
And the same can be done for pg_shdepend.
> On 31 Aug 2020, at 09:56, Michael Paquier <michael@paquier.xyz> wrote:
> +#define MAX_CATALOG_INSERT_BYTES 65535
> This name, and inclusion in a headerfile, implies that the definition is
> somewhat generic as opposed to its actual use. Using MULTIINSERT rather than
> INSERT in the name would clarify I reckon.
Makes sense, I have switched to MAX_CATALOG_MULTI_INSERT_BYTES.
> A few other comments:
>
> + /*
> + * Allocate the slots to use, but delay initialization until we know that
> + * they will be used.
> + */
> I think this comment warrants a longer explanation on why they wont all be
> used, or perhaps none of them (which is the real optimization win here).
Okay, I have updated the comments where this formulation is used.
Does that look adapted to you?
> + ObjectAddresses *addrs_auto;
> + ObjectAddresses *addrs_normal;
> It's not for this patch, but it seems a logical next step would be to be able
> to record the DependencyType as well when collecting deps rather than having to
> create multiple buckets.
Yeah, agreed. I am not sure yet how to design those APIs. One option
is to use a set of an array with DependencyType elements, each one
storing a list of dependencies of the same type.
> + /* Normal dependency from a domain to its collation. */
> + /* We know the default collation is pinned, so don't bother recording it */
> It's just moved and not introduced in this patch, but shouldn't these two lines
> be joined into a normal block comment?
Okay, done.
--
Michael
Attachments:
[text/x-diff] v3-0001-Use-multi-inserts-for-pg_depend.patch (12.0K, ../../20200903053506.GC14963@paquier.xyz/2-v3-0001-Use-multi-inserts-for-pg_depend.patch)
download | inline diff:
From 71cfefec57388d7d90ae169a8122bdb97a7bcd14 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Thu, 3 Sep 2020 14:23:48 +0900
Subject: [PATCH v3 1/2] Use multi-inserts for pg_depend
This is a follow-up of the work done in e3931d01. This case is a bit
different than pg_attribute and pg_shdepend: the maximum number of items
to insert is known in advance, but there is no need to handle pinned
dependencies. Hence, the base allocation for slots is done based on the
number of items and the maximum allowed with a cap at 64kB, and items
are initialized once used to minimize the overhead of the operation.
Some of the multi-insert logic is also simplified for pg_shdepend, as
per the feedback discussed for this specific patch.
Author: Daniel Gustafsson, Michael Paquier
Discussion: https://postgr.es/m/XXX
---
src/include/catalog/indexing.h | 6 +++
src/backend/catalog/heap.c | 8 +--
src/backend/catalog/pg_depend.c | 88 +++++++++++++++++++++++--------
src/backend/catalog/pg_shdepend.c | 66 +++++++++++------------
4 files changed, 106 insertions(+), 62 deletions(-)
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index a7e2a9b26b..d86729dc6c 100644
--- a/src/include/catalog/indexing.h
+++ b/src/include/catalog/indexing.h
@@ -29,6 +29,12 @@
*/
typedef struct ResultRelInfo *CatalogIndexState;
+/*
+ * Cap the maximum amount of bytes allocated for multi-inserts with system
+ * catalogs, limiting the number of slots used.
+ */
+#define MAX_CATALOG_MULTI_INSERT_BYTES 65535
+
/*
* indexing.c prototypes
*/
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index abd5bdb866..1201a93361 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -709,12 +709,6 @@ CheckAttributeType(const char *attname,
}
}
-/*
- * Cap the maximum amount of bytes allocated for InsertPgAttributeTuples()
- * slots.
- */
-#define MAX_PGATTRIBUTE_INSERT_BYTES 65535
-
/*
* InsertPgAttributeTuples
* Construct and insert a set of tuples in pg_attribute.
@@ -750,7 +744,7 @@ InsertPgAttributeTuples(Relation pg_attribute_rel,
/* Initialize the number of slots to use */
nslots = Min(tupdesc->natts,
- (MAX_PGATTRIBUTE_INSERT_BYTES / sizeof(FormData_pg_attribute)));
+ (MAX_CATALOG_MULTI_INSERT_BYTES / sizeof(FormData_pg_attribute)));
slot = palloc(sizeof(TupleTableSlot *) * nslots);
for (int i = 0; i < nslots; i++)
slot[i] = MakeSingleTupleTableSlot(td, &TTSOpsHeapTuple);
diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c
index 70baf03178..406e36ec00 100644
--- a/src/backend/catalog/pg_depend.c
+++ b/src/backend/catalog/pg_depend.c
@@ -59,10 +59,11 @@ recordMultipleDependencies(const ObjectAddress *depender,
{
Relation dependDesc;
CatalogIndexState indstate;
- HeapTuple tup;
- int i;
- bool nulls[Natts_pg_depend];
- Datum values[Natts_pg_depend];
+ TupleTableSlot **slot;
+ int i,
+ max_slots,
+ slot_init_count,
+ slot_stored_count;
if (nreferenced <= 0)
return; /* nothing to do */
@@ -76,11 +77,23 @@ recordMultipleDependencies(const ObjectAddress *depender,
dependDesc = table_open(DependRelationId, RowExclusiveLock);
+ /*
+ * Allocate the slots to use, but delay initialization until we know that
+ * they will be used. The slot initialization is the costly part, and the
+ * exact number of dependencies inserted cannot be known in advance as it
+ * depends on what is pinned by the system.
+ */
+ max_slots = Min(nreferenced,
+ MAX_CATALOG_MULTI_INSERT_BYTES / sizeof(FormData_pg_depend));
+ slot = palloc(sizeof(TupleTableSlot *) * max_slots);
+
/* Don't open indexes unless we need to make an update */
indstate = NULL;
- memset(nulls, false, sizeof(nulls));
-
+ /* number of slots currently storing tuples */
+ slot_stored_count = 0;
+ /* number of slots currently initialized */
+ slot_init_count = 0;
for (i = 0; i < nreferenced; i++, referenced++)
{
/*
@@ -88,38 +101,69 @@ recordMultipleDependencies(const ObjectAddress *depender,
* need to record dependencies on it. This saves lots of space in
* pg_depend, so it's worth the time taken to check.
*/
- if (!isObjectPinned(referenced, dependDesc))
+ if (isObjectPinned(referenced, dependDesc))
+ continue;
+
+ if (slot_init_count < max_slots)
{
- /*
- * Record the Dependency. Note we don't bother to check for
- * duplicate dependencies; there's no harm in them.
- */
- values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId);
- values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId);
- values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId);
+ slot[slot_stored_count] = MakeSingleTupleTableSlot(RelationGetDescr(dependDesc),
+ &TTSOpsHeapTuple);
+ slot_init_count++;
+ }
- values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId);
- values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId);
- values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId);
+ ExecClearTuple(slot[slot_stored_count]);
- values[Anum_pg_depend_deptype - 1] = CharGetDatum((char) behavior);
+ /*
+ * Record the Dependency. Note we don't bother to check for duplicate
+ * dependencies; there's no harm in them.
+ */
+ slot[slot_stored_count]->tts_values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId);
+ slot[slot_stored_count]->tts_values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId);
+ slot[slot_stored_count]->tts_values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId);
+ slot[slot_stored_count]->tts_values[Anum_pg_depend_deptype - 1] = CharGetDatum((char) behavior);
+ slot[slot_stored_count]->tts_values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId);
+ slot[slot_stored_count]->tts_values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId);
+ slot[slot_stored_count]->tts_values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId);
- tup = heap_form_tuple(dependDesc->rd_att, values, nulls);
+ memset(slot[slot_stored_count]->tts_isnull, false,
+ slot[slot_stored_count]->tts_tupleDescriptor->natts * sizeof(bool));
+ ExecStoreVirtualTuple(slot[slot_stored_count]);
+ slot_stored_count++;
+
+ /* If slots are full, insert a batch of tuples */
+ if (slot_stored_count == max_slots)
+ {
/* fetch index info only when we know we need it */
if (indstate == NULL)
indstate = CatalogOpenIndexes(dependDesc);
- CatalogTupleInsertWithInfo(dependDesc, tup, indstate);
-
- heap_freetuple(tup);
+ CatalogTuplesMultiInsertWithInfo(dependDesc, slot, slot_stored_count,
+ indstate);
+ slot_stored_count = 0;
}
}
+ /* Insert any tuples left in the buffer */
+ if (slot_stored_count > 0)
+ {
+ /* fetch index info only when we know we need it */
+ if (indstate == NULL)
+ indstate = CatalogOpenIndexes(dependDesc);
+
+ CatalogTuplesMultiInsertWithInfo(dependDesc, slot, slot_stored_count,
+ indstate);
+ }
+
if (indstate != NULL)
CatalogCloseIndexes(indstate);
table_close(dependDesc, RowExclusiveLock);
+
+ /* Drop only the number of slots used */
+ for (i = 0; i < slot_init_count; i++)
+ ExecDropSingleTupleTableSlot(slot[i]);
+ pfree(slot);
}
/*
diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c
index 30b234e90e..81cd8689d5 100644
--- a/src/backend/catalog/pg_shdepend.c
+++ b/src/backend/catalog/pg_shdepend.c
@@ -786,12 +786,6 @@ checkSharedDependencies(Oid classId, Oid objectId,
}
-/*
- * Cap the maximum amount of bytes allocated for copyTemplateDependencies()
- * slots.
- */
-#define MAX_PGSHDEPEND_INSERT_BYTES 65535
-
/*
* copyTemplateDependencies
*
@@ -806,21 +800,22 @@ copyTemplateDependencies(Oid templateDbId, Oid newDbId)
ScanKeyData key[1];
SysScanDesc scan;
HeapTuple tup;
- int slotCount;
CatalogIndexState indstate;
TupleTableSlot **slot;
- int nslots,
- max_slots;
- bool slot_init = true;
+ int max_slots,
+ slot_init_count,
+ slot_stored_count;
sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
sdepDesc = RelationGetDescr(sdepRel);
/*
* Allocate the slots to use, but delay initialization until we know that
- * they will be used.
+ * they will be used. A full scan of pg_shdepend is done to find all the
+ * dependencies from the template database to copy. Their number is not
+ * known in advance and the slot initialization is the costly part.
*/
- max_slots = MAX_PGSHDEPEND_INSERT_BYTES / sizeof(FormData_pg_shdepend);
+ max_slots = MAX_CATALOG_MULTI_INSERT_BYTES / sizeof(FormData_pg_shdepend);
slot = palloc(sizeof(TupleTableSlot *) * max_slots);
indstate = CatalogOpenIndexes(sdepRel);
@@ -834,6 +829,11 @@ copyTemplateDependencies(Oid templateDbId, Oid newDbId)
scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
NULL, 1, key);
+ /* number of slots currently storing tuples */
+ slot_stored_count = 0;
+ /* number of slots currently initialized */
+ slot_init_count = 0;
+
/*
* Copy the entries of the original database, changing the database Id to
* that of the new database. Note that because we are not copying rows
@@ -841,41 +841,42 @@ copyTemplateDependencies(Oid templateDbId, Oid newDbId)
* copy the ownership dependency of the template database itself; this is
* what we want.
*/
- slotCount = 0;
while (HeapTupleIsValid(tup = systable_getnext(scan)))
{
Form_pg_shdepend shdep;
- if (slot_init)
- slot[slotCount] = MakeSingleTupleTableSlot(sdepDesc, &TTSOpsHeapTuple);
+ if (slot_init_count < max_slots)
+ {
+ slot[slot_stored_count] = MakeSingleTupleTableSlot(sdepDesc, &TTSOpsHeapTuple);
+ slot_init_count++;
+ }
- ExecClearTuple(slot[slotCount]);
+ ExecClearTuple(slot[slot_stored_count]);
shdep = (Form_pg_shdepend) GETSTRUCT(tup);
- slot[slotCount]->tts_values[Anum_pg_shdepend_dbid] = ObjectIdGetDatum(newDbId);
- slot[slotCount]->tts_values[Anum_pg_shdepend_classid] = shdep->classid;
- slot[slotCount]->tts_values[Anum_pg_shdepend_objid] = shdep->objid;
- slot[slotCount]->tts_values[Anum_pg_shdepend_objsubid] = shdep->objsubid;
- slot[slotCount]->tts_values[Anum_pg_shdepend_refclassid] = shdep->refclassid;
- slot[slotCount]->tts_values[Anum_pg_shdepend_refobjid] = shdep->refobjid;
- slot[slotCount]->tts_values[Anum_pg_shdepend_deptype] = shdep->deptype;
+ slot[slot_stored_count]->tts_values[Anum_pg_shdepend_dbid] = ObjectIdGetDatum(newDbId);
+ slot[slot_stored_count]->tts_values[Anum_pg_shdepend_classid] = shdep->classid;
+ slot[slot_stored_count]->tts_values[Anum_pg_shdepend_objid] = shdep->objid;
+ slot[slot_stored_count]->tts_values[Anum_pg_shdepend_objsubid] = shdep->objsubid;
+ slot[slot_stored_count]->tts_values[Anum_pg_shdepend_refclassid] = shdep->refclassid;
+ slot[slot_stored_count]->tts_values[Anum_pg_shdepend_refobjid] = shdep->refobjid;
+ slot[slot_stored_count]->tts_values[Anum_pg_shdepend_deptype] = shdep->deptype;
- ExecStoreVirtualTuple(slot[slotCount]);
- slotCount++;
+ ExecStoreVirtualTuple(slot[slot_stored_count]);
+ slot_stored_count++;
/* If slots are full, insert a batch of tuples */
- if (slotCount == max_slots)
+ if (slot_stored_count == max_slots)
{
- CatalogTuplesMultiInsertWithInfo(sdepRel, slot, slotCount, indstate);
- slotCount = 0;
- slot_init = false;
+ CatalogTuplesMultiInsertWithInfo(sdepRel, slot, slot_stored_count, indstate);
+ slot_stored_count = 0;
}
}
/* Insert any tuples left in the buffer */
- if (slotCount > 0)
- CatalogTuplesMultiInsertWithInfo(sdepRel, slot, slotCount, indstate);
+ if (slot_stored_count > 0)
+ CatalogTuplesMultiInsertWithInfo(sdepRel, slot, slot_stored_count, indstate);
systable_endscan(scan);
@@ -883,8 +884,7 @@ copyTemplateDependencies(Oid templateDbId, Oid newDbId)
table_close(sdepRel, RowExclusiveLock);
/* Drop only the number of slots used */
- nslots = slot_init ? slotCount : max_slots;
- for (int i = 0; i < nslots; i++)
+ for (int i = 0; i < slot_init_count; i++)
ExecDropSingleTupleTableSlot(slot[i]);
pfree(slot);
}
--
2.28.0
[text/x-diff] v3-0002-Switch-to-multi-insert-dependencies-for-many-code.patch (40.0K, ../../20200903053506.GC14963@paquier.xyz/3-v3-0002-Switch-to-multi-insert-dependencies-for-many-code.patch)
download | inline diff:
From eb7922dff032f522d23b3fd520131693a212f4b7 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Thu, 3 Sep 2020 14:29:21 +0900
Subject: [PATCH v3 2/2] Switch to multi-insert dependencies for many code
paths
This makes use of the new APIs to insert dependencies in groups, instead
of doing the operation one-by-one. Using the current layer of routines
available, only dependencies of the same type can be grouped, which is
what this patch achieves.
---
src/backend/catalog/heap.c | 59 +++++++-------
src/backend/catalog/index.c | 21 ++++-
src/backend/catalog/pg_aggregate.c | 23 +++---
src/backend/catalog/pg_cast.c | 28 ++++---
src/backend/catalog/pg_constraint.c | 34 +++++---
src/backend/catalog/pg_operator.c | 20 +++--
src/backend/catalog/pg_proc.c | 30 +++++---
src/backend/catalog/pg_range.c | 39 ++++------
src/backend/catalog/pg_type.c | 64 ++++++++-------
src/backend/commands/functioncmds.c | 34 ++++----
src/backend/commands/proclang.c | 24 +++---
src/backend/commands/tsearchcmds.c | 90 +++++++++++-----------
src/test/regress/expected/create_index.out | 6 +-
13 files changed, 252 insertions(+), 220 deletions(-)
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 1201a93361..3046de6643 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -1428,15 +1428,9 @@ heap_create_with_catalog(const char *relname,
{
ObjectAddress myself,
referenced;
+ ObjectAddresses *addrs;
- myself.classId = RelationRelationId;
- myself.objectId = relid;
- myself.objectSubId = 0;
-
- referenced.classId = NamespaceRelationId;
- referenced.objectId = relnamespace;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ ObjectAddressSet(myself, RelationRelationId, relid);
recordDependencyOnOwner(RelationRelationId, relid, ownerid);
@@ -1444,12 +1438,15 @@ heap_create_with_catalog(const char *relname,
recordDependencyOnCurrentExtension(&myself, false);
+ addrs = new_object_addresses();
+
+ ObjectAddressSet(referenced, NamespaceRelationId, relnamespace);
+ add_exact_object_address(&referenced, addrs);
+
if (reloftypeid)
{
- referenced.classId = TypeRelationId;
- referenced.objectId = reloftypeid;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ ObjectAddressSet(referenced, TypeRelationId, reloftypeid);
+ add_exact_object_address(&referenced, addrs);
}
/*
@@ -1462,11 +1459,12 @@ heap_create_with_catalog(const char *relname,
if (relkind == RELKIND_RELATION ||
relkind == RELKIND_MATVIEW)
{
- referenced.classId = AccessMethodRelationId;
- referenced.objectId = accessmtd;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ ObjectAddressSet(referenced, AccessMethodRelationId, accessmtd);
+ add_exact_object_address(&referenced, addrs);
}
+
+ record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+ free_object_addresses(addrs);
}
/* Post creation hook for new relation */
@@ -3574,6 +3572,7 @@ StorePartitionKey(Relation rel,
bool nulls[Natts_pg_partitioned_table];
ObjectAddress myself;
ObjectAddress referenced;
+ ObjectAddresses *addrs;
Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
@@ -3617,31 +3616,27 @@ StorePartitionKey(Relation rel,
table_close(pg_partitioned_table, RowExclusiveLock);
/* Mark this relation as dependent on a few things as follows */
- myself.classId = RelationRelationId;
- myself.objectId = RelationGetRelid(rel);
- myself.objectSubId = 0;
+ addrs = new_object_addresses();
+ ObjectAddressSet(myself, RelationRelationId, RelationGetRelid(rel));
/* Operator class and collation per key column */
for (i = 0; i < partnatts; i++)
{
- referenced.classId = OperatorClassRelationId;
- referenced.objectId = partopclass[i];
- referenced.objectSubId = 0;
-
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ ObjectAddressSet(referenced, OperatorClassRelationId, partopclass[i]);
+ add_exact_object_address(&referenced, addrs);
/* The default collation is pinned, so don't bother recording it */
if (OidIsValid(partcollation[i]) &&
partcollation[i] != DEFAULT_COLLATION_OID)
{
- referenced.classId = CollationRelationId;
- referenced.objectId = partcollation[i];
- referenced.objectSubId = 0;
-
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ ObjectAddressSet(referenced, CollationRelationId, partcollation[i]);
+ add_exact_object_address(&referenced, addrs);
}
}
+ record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+ free_object_addresses(addrs);
+
/*
* The partitioning columns are made internally dependent on the table,
* because we cannot drop any of them without dropping the whole table.
@@ -3653,10 +3648,8 @@ StorePartitionKey(Relation rel,
if (partattrs[i] == 0)
continue; /* ignore expressions here */
- referenced.classId = RelationRelationId;
- referenced.objectId = RelationGetRelid(rel);
- referenced.objectSubId = partattrs[i];
-
+ ObjectAddressSubSet(referenced, RelationRelationId,
+ RelationGetRelid(rel), partattrs[i]);
recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
}
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 1d662e9af4..b2c8cb320e 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -1018,6 +1018,7 @@ index_create(Relation heapRelation,
{
ObjectAddress myself,
referenced;
+ ObjectAddresses *addrs;
ObjectAddressSet(myself, RelationRelationId, indexRelationId);
@@ -1054,6 +1055,8 @@ index_create(Relation heapRelation,
{
bool have_simple_col = false;
+ addrs = new_object_addresses();
+
/* Create auto dependencies on simply-referenced columns */
for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
{
@@ -1062,7 +1065,7 @@ index_create(Relation heapRelation,
ObjectAddressSubSet(referenced, RelationRelationId,
heapRelationId,
indexInfo->ii_IndexAttrNumbers[i]);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
+ add_exact_object_address(&referenced, addrs);
have_simple_col = true;
}
}
@@ -1077,8 +1080,11 @@ index_create(Relation heapRelation,
{
ObjectAddressSet(referenced, RelationRelationId,
heapRelationId);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
+ add_exact_object_address(&referenced, addrs);
}
+
+ record_object_address_dependencies(&myself, addrs, DEPENDENCY_AUTO);
+ free_object_addresses(addrs);
}
/*
@@ -1096,7 +1102,11 @@ index_create(Relation heapRelation,
recordDependencyOn(&myself, &referenced, DEPENDENCY_PARTITION_SEC);
}
+ /* placeholder for normal dependencies */
+ addrs = new_object_addresses();
+
/* Store dependency on collations */
+
/* The default collation is pinned, so don't bother recording it */
for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
{
@@ -1105,7 +1115,7 @@ index_create(Relation heapRelation,
{
ObjectAddressSet(referenced, CollationRelationId,
collationObjectId[i]);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
}
@@ -1113,9 +1123,12 @@ index_create(Relation heapRelation,
for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
{
ObjectAddressSet(referenced, OperatorClassRelationId, classObjectId[i]);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
+ record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+ free_object_addresses(addrs);
+
/* Store dependencies on anything mentioned in index expressions */
if (indexInfo->ii_Expressions)
{
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index 89007ad1ed..a0554f0d79 100644
--- a/src/backend/catalog/pg_aggregate.c
+++ b/src/backend/catalog/pg_aggregate.c
@@ -105,6 +105,7 @@ AggregateCreate(const char *aggName,
int i;
ObjectAddress myself,
referenced;
+ ObjectAddresses *addrs;
AclResult aclresult;
/* sanity checks (caller should have caught these) */
@@ -741,66 +742,70 @@ AggregateCreate(const char *aggName,
* way.
*/
+ addrs = new_object_addresses();
+
/* Depends on transition function */
ObjectAddressSet(referenced, ProcedureRelationId, transfn);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
/* Depends on final function, if any */
if (OidIsValid(finalfn))
{
ObjectAddressSet(referenced, ProcedureRelationId, finalfn);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
/* Depends on combine function, if any */
if (OidIsValid(combinefn))
{
ObjectAddressSet(referenced, ProcedureRelationId, combinefn);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
/* Depends on serialization function, if any */
if (OidIsValid(serialfn))
{
ObjectAddressSet(referenced, ProcedureRelationId, serialfn);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
/* Depends on deserialization function, if any */
if (OidIsValid(deserialfn))
{
ObjectAddressSet(referenced, ProcedureRelationId, deserialfn);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
/* Depends on forward transition function, if any */
if (OidIsValid(mtransfn))
{
ObjectAddressSet(referenced, ProcedureRelationId, mtransfn);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
/* Depends on inverse transition function, if any */
if (OidIsValid(minvtransfn))
{
ObjectAddressSet(referenced, ProcedureRelationId, minvtransfn);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
/* Depends on final function, if any */
if (OidIsValid(mfinalfn))
{
ObjectAddressSet(referenced, ProcedureRelationId, mfinalfn);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
/* Depends on sort operator, if any */
if (OidIsValid(sortop))
{
ObjectAddressSet(referenced, OperatorRelationId, sortop);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
+ record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+ free_object_addresses(addrs);
return myself;
}
diff --git a/src/backend/catalog/pg_cast.c b/src/backend/catalog/pg_cast.c
index 5ea2b82b08..c03e82d74f 100644
--- a/src/backend/catalog/pg_cast.c
+++ b/src/backend/catalog/pg_cast.c
@@ -50,6 +50,7 @@ CastCreate(Oid sourcetypeid, Oid targettypeid, Oid funcid, char castcontext,
bool nulls[Natts_pg_cast];
ObjectAddress myself,
referenced;
+ ObjectAddresses *addrs;
relation = table_open(CastRelationId, RowExclusiveLock);
@@ -83,32 +84,29 @@ CastCreate(Oid sourcetypeid, Oid targettypeid, Oid funcid, char castcontext,
CatalogTupleInsert(relation, tuple);
+ addrs = new_object_addresses();
+
/* make dependency entries */
- myself.classId = CastRelationId;
- myself.objectId = castid;
- myself.objectSubId = 0;
+ ObjectAddressSet(myself, CastRelationId, castid);
/* dependency on source type */
- referenced.classId = TypeRelationId;
- referenced.objectId = sourcetypeid;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, behavior);
+ ObjectAddressSet(referenced, TypeRelationId, sourcetypeid);
+ add_exact_object_address(&referenced, addrs);
/* dependency on target type */
- referenced.classId = TypeRelationId;
- referenced.objectId = targettypeid;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, behavior);
+ ObjectAddressSet(referenced, TypeRelationId, targettypeid);
+ add_exact_object_address(&referenced, addrs);
/* dependency on function */
if (OidIsValid(funcid))
{
- referenced.classId = ProcedureRelationId;
- referenced.objectId = funcid;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, behavior);
+ ObjectAddressSet(referenced, ProcedureRelationId, funcid);
+ add_exact_object_address(&referenced, addrs);
}
+ record_object_address_dependencies(&myself, addrs, behavior);
+ free_object_addresses(addrs);
+
/* dependency on extension */
recordDependencyOnCurrentExtension(&myself, false);
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index 6a6b2cb8c0..8764e6529d 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -91,6 +91,8 @@ CreateConstraintEntry(const char *constraintName,
NameData cname;
int i;
ObjectAddress conobject;
+ ObjectAddresses *addrs_auto;
+ ObjectAddresses *addrs_normal;
conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
@@ -227,6 +229,9 @@ CreateConstraintEntry(const char *constraintName,
table_close(conDesc, RowExclusiveLock);
+ /* Handle set of auto dependencies */
+ addrs_auto = new_object_addresses();
+
if (OidIsValid(relId))
{
/*
@@ -241,13 +246,13 @@ CreateConstraintEntry(const char *constraintName,
{
ObjectAddressSubSet(relobject, RelationRelationId, relId,
constraintKey[i]);
- recordDependencyOn(&conobject, &relobject, DEPENDENCY_AUTO);
+ add_exact_object_address(&relobject, addrs_auto);
}
}
else
{
ObjectAddressSet(relobject, RelationRelationId, relId);
- recordDependencyOn(&conobject, &relobject, DEPENDENCY_AUTO);
+ add_exact_object_address(&relobject, addrs_auto);
}
}
@@ -259,9 +264,16 @@ CreateConstraintEntry(const char *constraintName,
ObjectAddress domobject;
ObjectAddressSet(domobject, TypeRelationId, domainId);
- recordDependencyOn(&conobject, &domobject, DEPENDENCY_AUTO);
+ add_exact_object_address(&domobject, addrs_auto);
}
+ record_object_address_dependencies(&conobject, addrs_auto,
+ DEPENDENCY_AUTO);
+ free_object_addresses(addrs_auto);
+
+ /* Handle set if normal dependencies */
+ addrs_normal = new_object_addresses();
+
if (OidIsValid(foreignRelId))
{
/*
@@ -276,13 +288,13 @@ CreateConstraintEntry(const char *constraintName,
{
ObjectAddressSubSet(relobject, RelationRelationId,
foreignRelId, foreignKey[i]);
- recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL);
+ add_exact_object_address(&relobject, addrs_normal);
}
}
else
{
ObjectAddressSet(relobject, RelationRelationId, foreignRelId);
- recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL);
+ add_exact_object_address(&relobject, addrs_normal);
}
}
@@ -297,7 +309,7 @@ CreateConstraintEntry(const char *constraintName,
ObjectAddress relobject;
ObjectAddressSet(relobject, RelationRelationId, indexRelId);
- recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL);
+ add_exact_object_address(&relobject, addrs_normal);
}
if (foreignNKeys > 0)
@@ -316,20 +328,24 @@ CreateConstraintEntry(const char *constraintName,
for (i = 0; i < foreignNKeys; i++)
{
oprobject.objectId = pfEqOp[i];
- recordDependencyOn(&conobject, &oprobject, DEPENDENCY_NORMAL);
+ add_exact_object_address(&oprobject, addrs_normal);
if (ppEqOp[i] != pfEqOp[i])
{
oprobject.objectId = ppEqOp[i];
- recordDependencyOn(&conobject, &oprobject, DEPENDENCY_NORMAL);
+ add_exact_object_address(&oprobject, addrs_normal);
}
if (ffEqOp[i] != pfEqOp[i])
{
oprobject.objectId = ffEqOp[i];
- recordDependencyOn(&conobject, &oprobject, DEPENDENCY_NORMAL);
+ add_exact_object_address(&oprobject, addrs_normal);
}
}
}
+ record_object_address_dependencies(&conobject, addrs_normal,
+ DEPENDENCY_NORMAL);
+ free_object_addresses(addrs_normal);
+
/*
* We don't bother to register dependencies on the exclusion operators of
* an exclusion constraint. We assume they are members of the opclass
diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c
index 65a36be5ee..f7c07c9b5b 100644
--- a/src/backend/catalog/pg_operator.c
+++ b/src/backend/catalog/pg_operator.c
@@ -775,6 +775,7 @@ makeOperatorDependencies(HeapTuple tuple, bool isUpdate)
Form_pg_operator oper = (Form_pg_operator) GETSTRUCT(tuple);
ObjectAddress myself,
referenced;
+ ObjectAddresses *addrs;
ObjectAddressSet(myself, OperatorRelationId, oper->oid);
@@ -788,32 +789,34 @@ makeOperatorDependencies(HeapTuple tuple, bool isUpdate)
deleteSharedDependencyRecordsFor(myself.classId, myself.objectId, 0);
}
+ addrs = new_object_addresses();
+
/* Dependency on namespace */
if (OidIsValid(oper->oprnamespace))
{
ObjectAddressSet(referenced, NamespaceRelationId, oper->oprnamespace);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
/* Dependency on left type */
if (OidIsValid(oper->oprleft))
{
ObjectAddressSet(referenced, TypeRelationId, oper->oprleft);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
/* Dependency on right type */
if (OidIsValid(oper->oprright))
{
ObjectAddressSet(referenced, TypeRelationId, oper->oprright);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
/* Dependency on result type */
if (OidIsValid(oper->oprresult))
{
ObjectAddressSet(referenced, TypeRelationId, oper->oprresult);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
/*
@@ -829,23 +832,26 @@ makeOperatorDependencies(HeapTuple tuple, bool isUpdate)
if (OidIsValid(oper->oprcode))
{
ObjectAddressSet(referenced, ProcedureRelationId, oper->oprcode);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
/* Dependency on restriction selectivity function */
if (OidIsValid(oper->oprrest))
{
ObjectAddressSet(referenced, ProcedureRelationId, oper->oprrest);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
/* Dependency on join selectivity function */
if (OidIsValid(oper->oprjoin))
{
ObjectAddressSet(referenced, ProcedureRelationId, oper->oprjoin);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
+ record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+ free_object_addresses(addrs);
+
/* Dependency on owner */
recordDependencyOnOwner(OperatorRelationId, oper->oid,
oper->oprowner);
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index a28ab74d60..40d65dc6ba 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -114,6 +114,7 @@ ProcedureCreate(const char *procedureName,
char *detailmsg;
int i;
Oid trfid;
+ ObjectAddresses *addrs;
/*
* sanity checks
@@ -585,53 +586,58 @@ ProcedureCreate(const char *procedureName,
if (is_update)
deleteDependencyRecordsFor(ProcedureRelationId, retval, true);
+ addrs = new_object_addresses();
+
ObjectAddressSet(myself, ProcedureRelationId, retval);
/* dependency on namespace */
ObjectAddressSet(referenced, NamespaceRelationId, procNamespace);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
/* dependency on implementation language */
ObjectAddressSet(referenced, LanguageRelationId, languageObjectId);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
/* dependency on return type */
ObjectAddressSet(referenced, TypeRelationId, returnType);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
/* dependency on transform used by return type, if any */
if ((trfid = get_transform_oid(returnType, languageObjectId, true)))
{
ObjectAddressSet(referenced, TransformRelationId, trfid);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
/* dependency on parameter types */
for (i = 0; i < allParamCount; i++)
{
ObjectAddressSet(referenced, TypeRelationId, allParams[i]);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
/* dependency on transform used by parameter type, if any */
if ((trfid = get_transform_oid(allParams[i], languageObjectId, true)))
{
ObjectAddressSet(referenced, TransformRelationId, trfid);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
}
- /* dependency on parameter default expressions */
- if (parameterDefaults)
- recordDependencyOnExpr(&myself, (Node *) parameterDefaults,
- NIL, DEPENDENCY_NORMAL);
-
/* dependency on support function, if any */
if (OidIsValid(prosupport))
{
ObjectAddressSet(referenced, ProcedureRelationId, prosupport);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
+ record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+ free_object_addresses(addrs);
+
+ /* dependency on parameter default expressions */
+ if (parameterDefaults)
+ recordDependencyOnExpr(&myself, (Node *) parameterDefaults,
+ NIL, DEPENDENCY_NORMAL);
+
/* dependency on owner */
if (!is_update)
recordDependencyOnOwner(ProcedureRelationId, retval, proowner);
diff --git a/src/backend/catalog/pg_range.c b/src/backend/catalog/pg_range.c
index b5bc36c2bd..a606d8c3ad 100644
--- a/src/backend/catalog/pg_range.c
+++ b/src/backend/catalog/pg_range.c
@@ -43,6 +43,7 @@ RangeCreate(Oid rangeTypeOid, Oid rangeSubType, Oid rangeCollation,
HeapTuple tup;
ObjectAddress myself;
ObjectAddress referenced;
+ ObjectAddresses *addrs;
pg_range = table_open(RangeRelationId, RowExclusiveLock);
@@ -61,45 +62,37 @@ RangeCreate(Oid rangeTypeOid, Oid rangeSubType, Oid rangeCollation,
heap_freetuple(tup);
/* record type's dependencies on range-related items */
+ addrs = new_object_addresses();
- myself.classId = TypeRelationId;
- myself.objectId = rangeTypeOid;
- myself.objectSubId = 0;
+ ObjectAddressSet(myself, TypeRelationId, rangeTypeOid);
- referenced.classId = TypeRelationId;
- referenced.objectId = rangeSubType;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ ObjectAddressSet(referenced, TypeRelationId, rangeSubType);
+ add_exact_object_address(&referenced, addrs);
- referenced.classId = OperatorClassRelationId;
- referenced.objectId = rangeSubOpclass;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ ObjectAddressSet(referenced, OperatorClassRelationId, rangeSubOpclass);
+ add_exact_object_address(&referenced, addrs);
if (OidIsValid(rangeCollation))
{
- referenced.classId = CollationRelationId;
- referenced.objectId = rangeCollation;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ ObjectAddressSet(referenced, CollationRelationId, rangeCollation);
+ add_exact_object_address(&referenced, addrs);
}
if (OidIsValid(rangeCanonical))
{
- referenced.classId = ProcedureRelationId;
- referenced.objectId = rangeCanonical;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ ObjectAddressSet(referenced, ProcedureRelationId, rangeCanonical);
+ add_exact_object_address(&referenced, addrs);
}
if (OidIsValid(rangeSubDiff))
{
- referenced.classId = ProcedureRelationId;
- referenced.objectId = rangeSubDiff;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ ObjectAddressSet(referenced, ProcedureRelationId, rangeSubDiff);
+ add_exact_object_address(&referenced, addrs);
}
+ record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+ free_object_addresses(addrs);
+
table_close(pg_range, RowExclusiveLock);
}
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index 79ffe317dd..0b04dff773 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -554,6 +554,7 @@ GenerateTypeDependencies(HeapTuple typeTuple,
bool isNull;
ObjectAddress myself,
referenced;
+ ObjectAddresses *addrs_normal;
/* Extract defaultExpr if caller didn't pass it */
if (defaultExpr == NULL)
@@ -587,6 +588,10 @@ GenerateTypeDependencies(HeapTuple typeTuple,
* Skip these for a dependent type, since it will have such dependencies
* indirectly through its depended-on type or relation.
*/
+
+ /* placeholder for all normal dependencies */
+ addrs_normal = new_object_addresses();
+
if (!isDependentType)
{
ObjectAddressSet(referenced, NamespaceRelationId,
@@ -606,45 +611,70 @@ GenerateTypeDependencies(HeapTuple typeTuple,
if (OidIsValid(typeForm->typinput))
{
ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typinput);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs_normal);
}
if (OidIsValid(typeForm->typoutput))
{
ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typoutput);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs_normal);
}
if (OidIsValid(typeForm->typreceive))
{
ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typreceive);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs_normal);
}
if (OidIsValid(typeForm->typsend))
{
ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typsend);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs_normal);
}
if (OidIsValid(typeForm->typmodin))
{
ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typmodin);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs_normal);
}
if (OidIsValid(typeForm->typmodout))
{
ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typmodout);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs_normal);
}
if (OidIsValid(typeForm->typanalyze))
{
ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typanalyze);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs_normal);
}
+ /* Normal dependency from a domain to its base type. */
+ if (OidIsValid(typeForm->typbasetype))
+ {
+ ObjectAddressSet(referenced, TypeRelationId, typeForm->typbasetype);
+ add_exact_object_address(&referenced, addrs_normal);
+ }
+
+ /*
+ * Normal dependency from a domain to its collation. We know the default
+ * collation is pinned, so don't bother recording it.
+ */
+ if (OidIsValid(typeForm->typcollation) &&
+ typeForm->typcollation != DEFAULT_COLLATION_OID)
+ {
+ ObjectAddressSet(referenced, CollationRelationId, typeForm->typcollation);
+ add_exact_object_address(&referenced, addrs_normal);
+ }
+
+ record_object_address_dependencies(&myself, addrs_normal, DEPENDENCY_NORMAL);
+ free_object_addresses(addrs_normal);
+
+ /* Normal dependency on the default expression. */
+ if (defaultExpr)
+ recordDependencyOnExpr(&myself, defaultExpr, NIL, DEPENDENCY_NORMAL);
+
/*
* If the type is a rowtype for a relation, mark it as internally
* dependent on the relation, *unless* it is a stand-alone composite type
@@ -675,26 +705,6 @@ GenerateTypeDependencies(HeapTuple typeTuple,
recordDependencyOn(&myself, &referenced,
isImplicitArray ? DEPENDENCY_INTERNAL : DEPENDENCY_NORMAL);
}
-
- /* Normal dependency from a domain to its base type. */
- if (OidIsValid(typeForm->typbasetype))
- {
- ObjectAddressSet(referenced, TypeRelationId, typeForm->typbasetype);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
- }
-
- /* Normal dependency from a domain to its collation. */
- /* We know the default collation is pinned, so don't bother recording it */
- if (OidIsValid(typeForm->typcollation) &&
- typeForm->typcollation != DEFAULT_COLLATION_OID)
- {
- ObjectAddressSet(referenced, CollationRelationId, typeForm->typcollation);
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
- }
-
- /* Normal dependency on the default expression. */
- if (defaultExpr)
- recordDependencyOnExpr(&myself, defaultExpr, NIL, DEPENDENCY_NORMAL);
}
/*
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 1b5bdcec8b..e236581a8e 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -1696,6 +1696,7 @@ CreateTransform(CreateTransformStmt *stmt)
Relation relation;
ObjectAddress myself,
referenced;
+ ObjectAddresses *addrs;
bool is_replace;
/*
@@ -1836,39 +1837,34 @@ CreateTransform(CreateTransformStmt *stmt)
if (is_replace)
deleteDependencyRecordsFor(TransformRelationId, transformid, true);
+ addrs = new_object_addresses();
+
/* make dependency entries */
- myself.classId = TransformRelationId;
- myself.objectId = transformid;
- myself.objectSubId = 0;
+ ObjectAddressSet(myself, TransformRelationId, transformid);
/* dependency on language */
- referenced.classId = LanguageRelationId;
- referenced.objectId = langid;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ ObjectAddressSet(referenced, LanguageRelationId, langid);
+ add_exact_object_address(&referenced, addrs);
/* dependency on type */
- referenced.classId = TypeRelationId;
- referenced.objectId = typeid;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ ObjectAddressSet(referenced, TypeRelationId, typeid);
+ add_exact_object_address(&referenced, addrs);
/* dependencies on functions */
if (OidIsValid(fromsqlfuncid))
{
- referenced.classId = ProcedureRelationId;
- referenced.objectId = fromsqlfuncid;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ ObjectAddressSet(referenced, ProcedureRelationId, fromsqlfuncid);
+ add_exact_object_address(&referenced, addrs);
}
if (OidIsValid(tosqlfuncid))
{
- referenced.classId = ProcedureRelationId;
- referenced.objectId = tosqlfuncid;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ ObjectAddressSet(referenced, ProcedureRelationId, tosqlfuncid);
+ add_exact_object_address(&referenced, addrs);
}
+ record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+ free_object_addresses(addrs);
+
/* dependency on extension */
recordDependencyOnCurrentExtension(&myself, is_replace);
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 14153426bd..8ef60374f5 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -57,6 +57,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
bool is_update;
ObjectAddress myself,
referenced;
+ ObjectAddresses *addrs;
/*
* Check permission
@@ -186,30 +187,29 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
/* dependency on extension */
recordDependencyOnCurrentExtension(&myself, is_update);
+ addrs = new_object_addresses();
+
/* dependency on the PL handler function */
- referenced.classId = ProcedureRelationId;
- referenced.objectId = handlerOid;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ ObjectAddressSet(referenced, ProcedureRelationId, handlerOid);
+ add_exact_object_address(&referenced, addrs);
/* dependency on the inline handler function, if any */
if (OidIsValid(inlineOid))
{
- referenced.classId = ProcedureRelationId;
- referenced.objectId = inlineOid;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ ObjectAddressSet(referenced, ProcedureRelationId, inlineOid);
+ add_exact_object_address(&referenced, addrs);
}
/* dependency on the validator function, if any */
if (OidIsValid(valOid))
{
- referenced.classId = ProcedureRelationId;
- referenced.objectId = valOid;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ ObjectAddressSet(referenced, ProcedureRelationId, valOid);
+ add_exact_object_address(&referenced, addrs);
}
+ record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+ free_object_addresses(addrs);
+
/* Post creation hook for new procedural language */
InvokeObjectPostCreateHook(LanguageRelationId, myself.objectId, 0);
diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index 319a62012e..f5d1d137b8 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -133,42 +133,41 @@ makeParserDependencies(HeapTuple tuple)
Form_pg_ts_parser prs = (Form_pg_ts_parser) GETSTRUCT(tuple);
ObjectAddress myself,
referenced;
+ ObjectAddresses *addrs;
- myself.classId = TSParserRelationId;
- myself.objectId = prs->oid;
- myself.objectSubId = 0;
-
- /* dependency on namespace */
- referenced.classId = NamespaceRelationId;
- referenced.objectId = prs->prsnamespace;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ ObjectAddressSet(myself, TSParserRelationId, prs->oid);
/* dependency on extension */
recordDependencyOnCurrentExtension(&myself, false);
- /* dependencies on functions */
- referenced.classId = ProcedureRelationId;
- referenced.objectSubId = 0;
+ addrs = new_object_addresses();
- referenced.objectId = prs->prsstart;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ /* dependency on namespace */
+ ObjectAddressSet(referenced, NamespaceRelationId, prs->prsnamespace);
+ add_exact_object_address(&referenced, addrs);
+
+ /* dependencies on functions */
+ ObjectAddressSet(referenced, ProcedureRelationId, prs->prsstart);
+ add_exact_object_address(&referenced, addrs);
referenced.objectId = prs->prstoken;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
referenced.objectId = prs->prsend;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
referenced.objectId = prs->prslextype;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
if (OidIsValid(prs->prsheadline))
{
referenced.objectId = prs->prsheadline;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
+ record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+ free_object_addresses(addrs);
+
return myself;
}
@@ -304,16 +303,9 @@ makeDictionaryDependencies(HeapTuple tuple)
Form_pg_ts_dict dict = (Form_pg_ts_dict) GETSTRUCT(tuple);
ObjectAddress myself,
referenced;
+ ObjectAddresses *addrs;
- myself.classId = TSDictionaryRelationId;
- myself.objectId = dict->oid;
- myself.objectSubId = 0;
-
- /* dependency on namespace */
- referenced.classId = NamespaceRelationId;
- referenced.objectId = dict->dictnamespace;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ ObjectAddressSet(myself, TSDictionaryRelationId, dict->oid);
/* dependency on owner */
recordDependencyOnOwner(myself.classId, myself.objectId, dict->dictowner);
@@ -321,11 +313,18 @@ makeDictionaryDependencies(HeapTuple tuple)
/* dependency on extension */
recordDependencyOnCurrentExtension(&myself, false);
+ addrs = new_object_addresses();
+
+ /* dependency on namespace */
+ ObjectAddressSet(referenced, NamespaceRelationId, dict->dictnamespace);
+ add_exact_object_address(&referenced, addrs);
+
/* dependency on template */
- referenced.classId = TSTemplateRelationId;
- referenced.objectId = dict->dicttemplate;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ ObjectAddressSet(referenced, TSTemplateRelationId, dict->dicttemplate);
+ add_exact_object_address(&referenced, addrs);
+
+ record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+ free_object_addresses(addrs);
return myself;
}
@@ -649,33 +648,32 @@ makeTSTemplateDependencies(HeapTuple tuple)
Form_pg_ts_template tmpl = (Form_pg_ts_template) GETSTRUCT(tuple);
ObjectAddress myself,
referenced;
+ ObjectAddresses *addrs;
- myself.classId = TSTemplateRelationId;
- myself.objectId = tmpl->oid;
- myself.objectSubId = 0;
-
- /* dependency on namespace */
- referenced.classId = NamespaceRelationId;
- referenced.objectId = tmpl->tmplnamespace;
- referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ ObjectAddressSet(myself, TSTemplateRelationId, tmpl->oid);
/* dependency on extension */
recordDependencyOnCurrentExtension(&myself, false);
- /* dependencies on functions */
- referenced.classId = ProcedureRelationId;
- referenced.objectSubId = 0;
+ addrs = new_object_addresses();
- referenced.objectId = tmpl->tmpllexize;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ /* dependency on namespace */
+ ObjectAddressSet(referenced, NamespaceRelationId, tmpl->tmplnamespace);
+ add_exact_object_address(&referenced, addrs);
+
+ /* dependencies on functions */
+ ObjectAddressSet(referenced, ProcedureRelationId, tmpl->tmpllexize);
+ add_exact_object_address(&referenced, addrs);
if (OidIsValid(tmpl->tmplinit))
{
referenced.objectId = tmpl->tmplinit;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ add_exact_object_address(&referenced, addrs);
}
+ record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
+ free_object_addresses(addrs);
+
return myself;
}
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index e3e6634d7e..814416d936 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2069,11 +2069,10 @@ WHERE classid = 'pg_class'::regclass AND
index concur_reindex_ind3 | column c1 of table concur_reindex_tab | a
index concur_reindex_ind3 | table concur_reindex_tab | a
index concur_reindex_ind4 | column c1 of table concur_reindex_tab | a
- index concur_reindex_ind4 | column c1 of table concur_reindex_tab | a
index concur_reindex_ind4 | column c2 of table concur_reindex_tab | a
materialized view concur_reindex_matview | schema public | n
table concur_reindex_tab | schema public | n
-(9 rows)
+(8 rows)
REINDEX INDEX CONCURRENTLY concur_reindex_ind1;
REINDEX TABLE CONCURRENTLY concur_reindex_tab;
@@ -2097,11 +2096,10 @@ WHERE classid = 'pg_class'::regclass AND
index concur_reindex_ind3 | column c1 of table concur_reindex_tab | a
index concur_reindex_ind3 | table concur_reindex_tab | a
index concur_reindex_ind4 | column c1 of table concur_reindex_tab | a
- index concur_reindex_ind4 | column c1 of table concur_reindex_tab | a
index concur_reindex_ind4 | column c2 of table concur_reindex_tab | a
materialized view concur_reindex_matview | schema public | n
table concur_reindex_tab | schema public | n
-(9 rows)
+(8 rows)
-- Check that comments are preserved
CREATE TABLE testcomment (i int);
--
2.28.0
[application/pgp-signature] signature.asc (833B, ../../20200903053506.GC14963@paquier.xyz/4-signature.asc)
download
^ permalink raw reply [nested|flat] 694+ messages in thread
* Re: Switch to multi-inserts for pg_depend
2020-09-01 09:53 Re: Switch to multi-inserts for pg_depend Daniel Gustafsson <daniel@yesql.se>
2020-09-03 05:35 ` Re: Switch to multi-inserts for pg_depend Michael Paquier <michael@paquier.xyz>
@ 2020-09-03 07:47 ` Daniel Gustafsson <daniel@yesql.se>
2020-09-03 10:19 ` Re: Switch to multi-inserts for pg_depend Michael Paquier <michael@paquier.xyz>
1 sibling, 1 reply; 694+ messages in thread
From: Daniel Gustafsson @ 2020-09-03 07:47 UTC (permalink / raw)
To: Michael Paquier <michael@paquier.xyz>; +Cc: Alvaro Herrera <alvherre@2ndquadrant.com>; Robert Haas <robertmhaas@gmail.com>; Andres Freund <andres@anarazel.de>; Postgres hackers <pgsql-hackers@lists.postgresql.org>
> On 3 Sep 2020, at 07:35, Michael Paquier <michael@paquier.xyz> wrote:
>
> On Tue, Sep 01, 2020 at 11:53:36AM +0200, Daniel Gustafsson wrote:
>> On 14 Aug 2020, at 20:23, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:
>>
>>> The logic to keep track number of used slots used is baroque, though -- that
>>> could use a lot of simplification.
>>
>> What if slot_init was an integer which increments together with the loop
>> variable until max_slots is reached? If so, maybe it should be renamed
>> slot_init_count and slotCount renamed slot_stored_count to make the their use
>> clearer?
>
> Good idea, removing slot_init looks like a good thing for readability.
> And the same can be done for pg_shdepend.
I think this version is a clear improvement. Nothing more sticks out from a
read-through.
cheers ./daniel
^ permalink raw reply [nested|flat] 694+ messages in thread
* Re: Switch to multi-inserts for pg_depend
2020-09-01 09:53 Re: Switch to multi-inserts for pg_depend Daniel Gustafsson <daniel@yesql.se>
2020-09-03 05:35 ` Re: Switch to multi-inserts for pg_depend Michael Paquier <michael@paquier.xyz>
2020-09-03 07:47 ` Re: Switch to multi-inserts for pg_depend Daniel Gustafsson <daniel@yesql.se>
@ 2020-09-03 10:19 ` Michael Paquier <michael@paquier.xyz>
2020-09-03 10:47 ` Re: Switch to multi-inserts for pg_depend Daniel Gustafsson <daniel@yesql.se>
0 siblings, 1 reply; 694+ messages in thread
From: Michael Paquier @ 2020-09-03 10:19 UTC (permalink / raw)
To: Daniel Gustafsson <daniel@yesql.se>; +Cc: Alvaro Herrera <alvherre@2ndquadrant.com>; Robert Haas <robertmhaas@gmail.com>; Andres Freund <andres@anarazel.de>; Postgres hackers <pgsql-hackers@lists.postgresql.org>
On Thu, Sep 03, 2020 at 09:47:07AM +0200, Daniel Gustafsson wrote:
> I think this version is a clear improvement. Nothing more sticks out from a
> read-through.
Thanks for taking the time to look at it, Daniel. We of course could
still try to figure out how we could group all dependencies without
worrying about their type, but I'd like to leave that as future work
for now. This is much more complex than what's proposed on this
thread, and I am not sure if we really need to make this stuff more
complex for this purpose.
--
Michael
Attachments:
[application/pgp-signature] signature.asc (833B, ../../20200903101935.GA19499@paquier.xyz/2-signature.asc)
download
^ permalink raw reply [nested|flat] 694+ messages in thread
* Re: Switch to multi-inserts for pg_depend
2020-09-01 09:53 Re: Switch to multi-inserts for pg_depend Daniel Gustafsson <daniel@yesql.se>
2020-09-03 05:35 ` Re: Switch to multi-inserts for pg_depend Michael Paquier <michael@paquier.xyz>
2020-09-03 07:47 ` Re: Switch to multi-inserts for pg_depend Daniel Gustafsson <daniel@yesql.se>
2020-09-03 10:19 ` Re: Switch to multi-inserts for pg_depend Michael Paquier <michael@paquier.xyz>
@ 2020-09-03 10:47 ` Daniel Gustafsson <daniel@yesql.se>
0 siblings, 0 replies; 694+ messages in thread
From: Daniel Gustafsson @ 2020-09-03 10:47 UTC (permalink / raw)
To: Michael Paquier <michael@paquier.xyz>; +Cc: Alvaro Herrera <alvherre@2ndquadrant.com>; Robert Haas <robertmhaas@gmail.com>; Andres Freund <andres@anarazel.de>; Postgres hackers <pgsql-hackers@lists.postgresql.org>
> On 3 Sep 2020, at 12:19, Michael Paquier <michael@paquier.xyz> wrote:
>
> On Thu, Sep 03, 2020 at 09:47:07AM +0200, Daniel Gustafsson wrote:
>> I think this version is a clear improvement. Nothing more sticks out from a
>> read-through.
>
> Thanks for taking the time to look at it, Daniel. We of course could
> still try to figure out how we could group all dependencies without
> worrying about their type, but I'd like to leave that as future work
> for now. This is much more complex than what's proposed on this
> thread, and I am not sure if we really need to make this stuff more
> complex for this purpose.
Agreed, I think that's a separate piece of work and discussion.
cheers ./daniel
^ permalink raw reply [nested|flat] 694+ messages in thread
* Re: Switch to multi-inserts for pg_depend
2020-09-01 09:53 Re: Switch to multi-inserts for pg_depend Daniel Gustafsson <daniel@yesql.se>
2020-09-03 05:35 ` Re: Switch to multi-inserts for pg_depend Michael Paquier <michael@paquier.xyz>
@ 2020-09-03 14:50 ` Alvaro Herrera <alvherre@2ndquadrant.com>
2020-09-04 01:15 ` Re: Switch to multi-inserts for pg_depend Michael Paquier <michael@paquier.xyz>
1 sibling, 1 reply; 694+ messages in thread
From: Alvaro Herrera @ 2020-09-03 14:50 UTC (permalink / raw)
To: Michael Paquier <michael@paquier.xyz>; +Cc: Daniel Gustafsson <daniel@yesql.se>; Robert Haas <robertmhaas@gmail.com>; Andres Freund <andres@anarazel.de>; Postgres hackers <pgsql-hackers@lists.postgresql.org>
I agree, this version looks much better, thanks. Two very minor things:
On 2020-Sep-03, Michael Paquier wrote:
> @@ -76,11 +77,23 @@ recordMultipleDependencies(const ObjectAddress *depender,
>
> dependDesc = table_open(DependRelationId, RowExclusiveLock);
>
> + /*
> + * Allocate the slots to use, but delay initialization until we know that
> + * they will be used. The slot initialization is the costly part, and the
> + * exact number of dependencies inserted cannot be known in advance as it
> + * depends on what is pinned by the system.
> + */
I'm not sure you need the second sentence in this comment; keeping the
"delay initialization until ..." part seems sufficient. If you really
want to highlight that initialization is costly, maybe just say "delay
costly initialization".
> + /*
> + * Record the Dependency. Note we don't bother to check for duplicate
> + * dependencies; there's no harm in them.
> + */
No need to uppercase "dependency". (I know this is carried forward from
prior comment, but it was equally unnecessary there.)
> /*
> * Allocate the slots to use, but delay initialization until we know that
> - * they will be used.
> + * they will be used. A full scan of pg_shdepend is done to find all the
> + * dependencies from the template database to copy. Their number is not
> + * known in advance and the slot initialization is the costly part.
> */
As above, this change is not needed.
--
Álvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
^ permalink raw reply [nested|flat] 694+ messages in thread
* Re: Switch to multi-inserts for pg_depend
2020-09-01 09:53 Re: Switch to multi-inserts for pg_depend Daniel Gustafsson <daniel@yesql.se>
2020-09-03 05:35 ` Re: Switch to multi-inserts for pg_depend Michael Paquier <michael@paquier.xyz>
2020-09-03 14:50 ` Re: Switch to multi-inserts for pg_depend Alvaro Herrera <alvherre@2ndquadrant.com>
@ 2020-09-04 01:15 ` Michael Paquier <michael@paquier.xyz>
2020-09-05 13:21 ` Re: Switch to multi-inserts for pg_depend Michael Paquier <michael@paquier.xyz>
0 siblings, 1 reply; 694+ messages in thread
From: Michael Paquier @ 2020-09-04 01:15 UTC (permalink / raw)
To: Alvaro Herrera <alvherre@2ndquadrant.com>; +Cc: Daniel Gustafsson <daniel@yesql.se>; Robert Haas <robertmhaas@gmail.com>; Andres Freund <andres@anarazel.de>; Postgres hackers <pgsql-hackers@lists.postgresql.org>
On Thu, Sep 03, 2020 at 10:50:49AM -0400, Alvaro Herrera wrote:
> I'm not sure you need the second sentence in this comment; keeping the
> "delay initialization until ..." part seems sufficient. If you really
> want to highlight that initialization is costly, maybe just say "delay
> costly initialization".
Thanks for the review.
This extra comment was to answer to Daniel's suggestion upthread, and
the simple wording you are suggesting is much better than what I did,
so I have just added "costly initialization" in those two places.
>> + /*
>> + * Record the Dependency. Note we don't bother to check for duplicate
>> + * dependencies; there's no harm in them.
>> + */
>
> No need to uppercase "dependency". (I know this is carried forward from
> prior comment, but it was equally unnecessary there.)
Thanks, fixed.
--
Michael
Attachments:
[application/pgp-signature] signature.asc (833B, ../../20200904011557.GD19499@paquier.xyz/2-signature.asc)
download
^ permalink raw reply [nested|flat] 694+ messages in thread
* Re: Switch to multi-inserts for pg_depend
2020-09-01 09:53 Re: Switch to multi-inserts for pg_depend Daniel Gustafsson <daniel@yesql.se>
2020-09-03 05:35 ` Re: Switch to multi-inserts for pg_depend Michael Paquier <michael@paquier.xyz>
2020-09-03 14:50 ` Re: Switch to multi-inserts for pg_depend Alvaro Herrera <alvherre@2ndquadrant.com>
2020-09-04 01:15 ` Re: Switch to multi-inserts for pg_depend Michael Paquier <michael@paquier.xyz>
@ 2020-09-05 13:21 ` Michael Paquier <michael@paquier.xyz>
0 siblings, 0 replies; 694+ messages in thread
From: Michael Paquier @ 2020-09-05 13:21 UTC (permalink / raw)
To: Alvaro Herrera <alvherre@2ndquadrant.com>; +Cc: Daniel Gustafsson <daniel@yesql.se>; Robert Haas <robertmhaas@gmail.com>; Andres Freund <andres@anarazel.de>; Postgres hackers <pgsql-hackers@lists.postgresql.org>
On Fri, Sep 04, 2020 at 10:15:57AM +0900, Michael Paquier wrote:
> Thanks, fixed.
With the two comment fixes included, I have looked at both patches
again today, and applied them.
--
Michael
Attachments:
[application/pgp-signature] signature.asc (833B, ../../20200905132159.GB18115@paquier.xyz/2-signature.asc)
download
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ messages in thread
From: Nathan Bossart @ 2026-07-09 20:38 UTC (permalink / raw)
---
src/backend/storage/lmgr/lock.c | 57 ++++++++++----------------------
src/tools/pgindent/typedefs.list | 1 -
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..c5943d7fc74 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);
}
/*
@@ -3364,10 +3345,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);
}
}
@@ -4502,9 +4481,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);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 56c1f997f88..f4c989c8c30 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -846,7 +846,6 @@ FSMPageData
FakeRelCacheEntry
FakeRelCacheEntryData
FastPathMeta
-FastPathStrongRelationLockData
FdwInfo
FdwRoutine
FetchDirection
--
2.50.1 (Apple Git-155)
--Xf36GNcW+0xZNily--
^ permalink raw reply [nested|flat] 694+ messages in thread
* [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics
@ 2026-07-09 20:38 Nathan Bossart <nathan@postgresql.org>
0 siblings, 0 replies; 694+ 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] 694+ messages in thread
end of thread, other threads:[~2026-07-09 20:38 UTC | newest]
Thread overview: 694+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2020-09-01 09:53 Re: Switch to multi-inserts for pg_depend Daniel Gustafsson <daniel@yesql.se>
2020-09-03 05:35 ` Michael Paquier <michael@paquier.xyz>
2020-09-03 07:47 ` Daniel Gustafsson <daniel@yesql.se>
2020-09-03 10:19 ` Michael Paquier <michael@paquier.xyz>
2020-09-03 10:47 ` Daniel Gustafsson <daniel@yesql.se>
2020-09-03 14:50 ` Alvaro Herrera <alvherre@2ndquadrant.com>
2020-09-04 01:15 ` Michael Paquier <michael@paquier.xyz>
2020-09-05 13:21 ` Michael Paquier <michael@paquier.xyz>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v2 9/9] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
2026-07-09 20:38 [PATCH v1 8/8] convert FastPathStrongRelationLocks to atomics Nathan Bossart <nathan@postgresql.org>
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox