agora inbox for [email protected]  
help / color / mirror / Atom feed
[PATCH v25 3/4] Move conversion of a "historic" to MVCC snapshot to a separate function.
195+ messages / 2 participants
[nested] [flat]

* [PATCH v25 3/4] Move conversion of a "historic" to MVCC snapshot to a separate function.
@ 2025-08-11 13:23 Antonin Houska <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Antonin Houska @ 2025-08-11 13:23 UTC (permalink / raw)

The conversion is now handled by SnapBuildMVCCFromHistoric(). REPACK
CONCURRENTLY will also need it.
---
 src/backend/replication/logical/snapbuild.c | 51 +++++++++++++++++----
 src/backend/utils/time/snapmgr.c            |  3 +-
 src/include/replication/snapbuild.h         |  1 +
 src/include/utils/snapmgr.h                 |  1 +
 4 files changed, 45 insertions(+), 11 deletions(-)

diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index 98ddee20929..a2f1803622c 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -440,10 +440,7 @@ Snapshot
 SnapBuildInitialSnapshot(SnapBuild *builder)
 {
 	Snapshot	snap;
-	TransactionId xid;
 	TransactionId safeXid;
-	TransactionId *newxip;
-	int			newxcnt = 0;
 
 	Assert(XactIsoLevel == XACT_REPEATABLE_READ);
 	Assert(builder->building_full_snapshot);
@@ -485,6 +482,31 @@ SnapBuildInitialSnapshot(SnapBuild *builder)
 
 	MyProc->xmin = snap->xmin;
 
+	/* Convert the historic snapshot to MVCC snapshot. */
+	return SnapBuildMVCCFromHistoric(snap, true);
+}
+
+/*
+ * Turn a historic MVCC snapshot into an ordinary MVCC snapshot.
+ *
+ * Unlike a regular (non-historic) MVCC snapshot, the xip array of this
+ * snapshot contains not only running main transactions, but also their
+ * subtransactions. This difference does has no impact on XidInMVCCSnapshot().
+ *
+ * Pass true for 'in_place' if you don't care about modifying the source
+ * snapshot. If you need a new instance, and one that was allocated as a
+ * single chunk of memory, pass false.
+ */
+Snapshot
+SnapBuildMVCCFromHistoric(Snapshot snapshot, bool in_place)
+{
+	TransactionId xid;
+	TransactionId *oldxip = snapshot->xip;
+	uint32		oldxcnt = snapshot->xcnt;
+	TransactionId *newxip;
+	int			newxcnt = 0;
+	Snapshot	result;
+
 	/* allocate in transaction context */
 	newxip = (TransactionId *)
 		palloc(sizeof(TransactionId) * GetMaxSnapshotXidCount());
@@ -495,7 +517,7 @@ SnapBuildInitialSnapshot(SnapBuild *builder)
 	 * classical snapshot by marking all non-committed transactions as
 	 * in-progress. This can be expensive.
 	 */
-	for (xid = snap->xmin; NormalTransactionIdPrecedes(xid, snap->xmax);)
+	for (xid = snapshot->xmin; NormalTransactionIdPrecedes(xid, snapshot->xmax);)
 	{
 		void	   *test;
 
@@ -503,7 +525,7 @@ SnapBuildInitialSnapshot(SnapBuild *builder)
 		 * Check whether transaction committed using the decoding snapshot
 		 * meaning of ->xip.
 		 */
-		test = bsearch(&xid, snap->xip, snap->xcnt,
+		test = bsearch(&xid, snapshot->xip, snapshot->xcnt,
 					   sizeof(TransactionId), xidComparator);
 
 		if (test == NULL)
@@ -520,11 +542,22 @@ SnapBuildInitialSnapshot(SnapBuild *builder)
 	}
 
 	/* adjust remaining snapshot fields as needed */
-	snap->snapshot_type = SNAPSHOT_MVCC;
-	snap->xcnt = newxcnt;
-	snap->xip = newxip;
+	snapshot->xcnt = newxcnt;
+	snapshot->xip = newxip;
 
-	return snap;
+	if (in_place)
+		result = snapshot;
+	else
+	{
+		result = CopySnapshot(snapshot);
+
+		/* Restore the original values so the source is intact. */
+		snapshot->xip = oldxip;
+		snapshot->xcnt = oldxcnt;
+	}
+	result->snapshot_type = SNAPSHOT_MVCC;
+
+	return result;
 }
 
 /*
diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c
index 65561cc6bc3..bc7840052fe 100644
--- a/src/backend/utils/time/snapmgr.c
+++ b/src/backend/utils/time/snapmgr.c
@@ -212,7 +212,6 @@ typedef struct ExportedSnapshot
 static List *exportedSnapshots = NIL;
 
 /* Prototypes for local functions */
-static Snapshot CopySnapshot(Snapshot snapshot);
 static void UnregisterSnapshotNoOwner(Snapshot snapshot);
 static void FreeSnapshot(Snapshot snapshot);
 static void SnapshotResetXmin(void);
@@ -602,7 +601,7 @@ SetTransactionSnapshot(Snapshot sourcesnap, VirtualTransactionId *sourcevxid,
  * The copy is palloc'd in TopTransactionContext and has initial refcounts set
  * to 0.  The returned snapshot has the copied flag set.
  */
-static Snapshot
+Snapshot
 CopySnapshot(Snapshot snapshot)
 {
 	Snapshot	newsnap;
diff --git a/src/include/replication/snapbuild.h b/src/include/replication/snapbuild.h
index 44031dcf6e3..6d4d2d1814c 100644
--- a/src/include/replication/snapbuild.h
+++ b/src/include/replication/snapbuild.h
@@ -73,6 +73,7 @@ extern void FreeSnapshotBuilder(SnapBuild *builder);
 extern void SnapBuildSnapDecRefcount(Snapshot snap);
 
 extern Snapshot SnapBuildInitialSnapshot(SnapBuild *builder);
+extern Snapshot SnapBuildMVCCFromHistoric(Snapshot snapshot, bool in_place);
 extern const char *SnapBuildExportSnapshot(SnapBuild *builder);
 extern void SnapBuildClearExportedSnapshot(void);
 extern void SnapBuildResetExportedSnapshotState(void);
diff --git a/src/include/utils/snapmgr.h b/src/include/utils/snapmgr.h
index 604c1f90216..f65f83c85cd 100644
--- a/src/include/utils/snapmgr.h
+++ b/src/include/utils/snapmgr.h
@@ -63,6 +63,7 @@ extern Snapshot GetTransactionSnapshot(void);
 extern Snapshot GetLatestSnapshot(void);
 extern void SnapshotSetCommandId(CommandId curcid);
 
+extern Snapshot CopySnapshot(Snapshot snapshot);
 extern Snapshot GetCatalogSnapshot(Oid relid);
 extern Snapshot GetNonHistoricCatalogSnapshot(Oid relid);
 extern void InvalidateCatalogSnapshot(void);
-- 
2.47.3


--ecl2euvoqutt27wj
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
	filename="v25-0004-Add-CONCURRENTLY-option-to-REPACK-command.patch"



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread

* [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics
@ 2026-07-09 20:04 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 195+ messages in thread

From: Nathan Bossart @ 2026-07-09 20:04 UTC (permalink / raw)

---
 src/backend/utils/sort/tuplesort.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..81e0b2816d6 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -104,6 +104,7 @@
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "port/atomics.h"
 #include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "utils/guc.h"
@@ -340,9 +341,6 @@ struct Tuplesortstate
  */
 struct Sharedsort
 {
-	/* mutex protects all fields prior to tapes */
-	slock_t		mutex;
-
 	/*
 	 * currentWorker generates ordinal identifier numbers for parallel sort
 	 * workers.  These start from 0, and are always gapless.
@@ -351,8 +349,8 @@ struct Sharedsort
 	 * is equal to state.nParticipants within the leader, leader is ready to
 	 * merge worker runs.
 	 */
-	int			currentWorker;
-	int			workersFinished;
+	pg_atomic_uint32 currentWorker;
+	pg_atomic_uint32 workersFinished;
 
 	/* Temporary file space */
 	SharedFileSet fileset;
@@ -3252,9 +3250,8 @@ tuplesort_initialize_shared(Sharedsort *shared, int nWorkers, dsm_segment *seg)
 
 	Assert(nWorkers > 0);
 
-	SpinLockInit(&shared->mutex);
-	shared->currentWorker = 0;
-	shared->workersFinished = 0;
+	pg_atomic_init_u32(&shared->currentWorker, 0);
+	pg_atomic_init_u32(&shared->workersFinished, 0);
 	SharedFileSetInit(&shared->fileset, seg);
 	shared->nTapes = nWorkers;
 	for (i = 0; i < nWorkers; i++)
@@ -3291,16 +3288,9 @@ tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg)
 static int
 worker_get_identifier(Tuplesortstate *state)
 {
-	Sharedsort *shared = state->shared;
-	int			worker;
-
 	Assert(WORKER(state));
 
-	SpinLockAcquire(&shared->mutex);
-	worker = shared->currentWorker++;
-	SpinLockRelease(&shared->mutex);
-
-	return worker;
+	return pg_atomic_fetch_add_u32(&state->shared->currentWorker, 1);
 }
 
 /*
@@ -3342,10 +3332,8 @@ worker_freeze_result_tape(Tuplesortstate *state)
 	LogicalTapeFreeze(state->result_tape, &output);
 
 	/* Store properties of output tape, and update finished worker count */
-	SpinLockAcquire(&shared->mutex);
 	shared->tapes[state->worker] = output;
-	shared->workersFinished++;
-	SpinLockRelease(&shared->mutex);
+	pg_atomic_fetch_add_u32(&shared->workersFinished, 1);
 }
 
 /*
@@ -3387,9 +3375,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	Assert(LEADER(state));
 	Assert(nParticipants >= 1);
 
-	SpinLockAcquire(&shared->mutex);
-	workersFinished = shared->workersFinished;
-	SpinLockRelease(&shared->mutex);
+	workersFinished = pg_atomic_read_membarrier_u32(&shared->workersFinished);
 
 	if (nParticipants != workersFinished)
 		elog(ERROR, "cannot take over tapes before all workers finish");
-- 
2.50.1 (Apple Git-155)


--Ot5x3ffkWEuxilWO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0006-convert-SharedFileSet-refcnt-to-an-atomic.patch



^ permalink  raw  reply  [nested|flat] 195+ messages in thread


end of thread, other threads:[~2026-07-09 20:04 UTC | newest]

Thread overview: 195+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2025-08-11 13:23 [PATCH v25 3/4] Move conversion of a "historic" to MVCC snapshot to a separate function. Antonin Houska <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>
2026-07-09 20:04 [PATCH v1 5/8] convert Sharedsort->{currentWorker,workersFinished} to atomics Nathan Bossart <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox