Obsolete use of volatile in walsender.c, walreceiver.c, walreceiverfuncs.c?

Started by Thomas Munroover 10 years ago10 messages
#1Thomas Munro
thomas.munro@enterprisedb.com
1 attachment(s)

Hi

In walsender.c, walreceiver.c, walreceiverfuncs.c there are several
places where volatile qualifiers are used apparently only to prevent
reordering around spinlock operations. My understanding is that if
potential load/store reordering around spinlock operations is the only
reason for using volatile, 0709b7ee72e4bc71ad07b7120acd117265ab51d0
made it unnecessary. For example see
6ba4ecbf477e0b25dd7bde1b0c4e07fc2da19348 which stripped some volatile
qualifiers out of xlog.c.

I did notice that sometimes walsnd->pid is read without acquiring the
spinlock. Is that actually OK anyway (taking a stale and inconsistent
view of the contents of walsnd->pid WRT to the other members that are
later accessed while holding the spinlock)?

Would it be safe to remove all those volatile qualifiers, something
like in the attached, or am I missing something?

(There is also code in syncrep.c that is reading shmem without
acquiring spinlocks using volatile qualifiers, that is a different
situation, though I don't yet see how it is ordering sensitive or
reading the same object repeatedly, but I'm not talking about that
here).

--
Thomas Munro
http://www.enterprisedb.com

Attachments:

replication-strip-volatile.patchapplication/octet-stream; name=replication-strip-volatile.patchDownload
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index 41e57f2..183a3a5 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -192,9 +192,7 @@ WalReceiverMain(void)
 	TimeLineID	startpointTLI;
 	TimeLineID	primaryTLI;
 	bool		first_stream;
-
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 	TimestampTz last_recv_timestamp;
 	bool		ping_sent;
 
@@ -559,8 +557,7 @@ WalReceiverMain(void)
 static void
 WalRcvWaitForStartPosition(XLogRecPtr *startpoint, TimeLineID *startpointTLI)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 	int			state;
 
 	SpinLockAcquire(&walrcv->mutex);
@@ -693,8 +690,7 @@ WalRcvFetchTimeLineHistoryFiles(TimeLineID first, TimeLineID last)
 static void
 WalRcvDie(int code, Datum arg)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 
 	/* Ensure that all WAL records received are flushed to disk */
 	XLogWalRcvFlush(true);
@@ -974,8 +970,7 @@ XLogWalRcvFlush(bool dying)
 {
 	if (LogstreamResult.Flush < LogstreamResult.Write)
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalRcvData *walrcv = WalRcv;
+		WalRcvData *walrcv = WalRcv;
 
 		issue_xlog_fsync(recvFile, recvSegNo);
 
@@ -1179,8 +1174,7 @@ XLogWalRcvSendHSFeedback(bool immed)
 static void
 ProcessWalSndrMessage(XLogRecPtr walEnd, TimestampTz sendTime)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 
 	TimestampTz lastMsgReceiptTime = GetCurrentTimestamp();
 
diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c
index f77a790..4452f25 100644
--- a/src/backend/replication/walreceiverfuncs.c
+++ b/src/backend/replication/walreceiverfuncs.c
@@ -72,8 +72,7 @@ WalRcvShmemInit(void)
 bool
 WalRcvRunning(void)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 	WalRcvState state;
 	pg_time_t	startTime;
 
@@ -118,8 +117,7 @@ WalRcvRunning(void)
 bool
 WalRcvStreaming(void)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 	WalRcvState state;
 	pg_time_t	startTime;
 
@@ -165,8 +163,7 @@ WalRcvStreaming(void)
 void
 ShutdownWalRcv(void)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 	pid_t		walrcvpid = 0;
 
 	/*
@@ -227,8 +224,7 @@ void
 RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo,
 					 const char *slotname)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 	bool		launch = false;
 	pg_time_t	now = (pg_time_t) time(NULL);
 
@@ -298,8 +294,7 @@ RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo,
 XLogRecPtr
 GetWalRcvWriteRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 	XLogRecPtr	recptr;
 
 	SpinLockAcquire(&walrcv->mutex);
@@ -320,9 +315,7 @@ GetWalRcvWriteRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI)
 int
 GetReplicationApplyDelay(void)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
-
+	WalRcvData *walrcv = WalRcv;
 	XLogRecPtr	receivePtr;
 	XLogRecPtr	replayPtr;
 
@@ -359,8 +352,7 @@ GetReplicationApplyDelay(void)
 int
 GetReplicationTransferLatency(void)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 
 	TimestampTz lastMsgSendTime;
 	TimestampTz lastMsgReceiptTime;
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index c95fe75..c6043cd 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -641,8 +641,7 @@ StartReplication(StartReplicationCmd *cmd)
 
 		/* Initialize shared memory status, too */
 		{
-			/* use volatile pointer to prevent code rearrangement */
-			volatile WalSnd *walsnd = MyWalSnd;
+			WalSnd *walsnd = MyWalSnd;
 
 			SpinLockAcquire(&walsnd->mutex);
 			walsnd->sentPtr = sentPtr;
@@ -990,8 +989,7 @@ StartLogicalReplication(StartReplicationCmd *cmd)
 
 	/* Also update the sent position status in shared memory */
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = MyWalSnd;
+		WalSnd *walsnd = MyWalSnd;
 
 		SpinLockAcquire(&walsnd->mutex);
 		walsnd->sentPtr = MyReplicationSlot->data.restart_lsn;
@@ -1494,9 +1492,7 @@ static void
 PhysicalConfirmReceivedLocation(XLogRecPtr lsn)
 {
 	bool		changed = false;
-
-	/* use volatile pointer to prevent code rearrangement */
-	volatile ReplicationSlot *slot = MyReplicationSlot;
+	ReplicationSlot *slot = MyReplicationSlot;
 
 	Assert(lsn != InvalidXLogRecPtr);
 	SpinLockAcquire(&slot->mutex);
@@ -1554,8 +1550,7 @@ ProcessStandbyReplyMessage(void)
 	 * standby.
 	 */
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = MyWalSnd;
+		WalSnd *walsnd = MyWalSnd;
 
 		SpinLockAcquire(&walsnd->mutex);
 		walsnd->write = writePtr;
@@ -1584,7 +1579,7 @@ static void
 PhysicalReplicationSlotNewXmin(TransactionId feedbackXmin)
 {
 	bool		changed = false;
-	volatile ReplicationSlot *slot = MyReplicationSlot;
+	ReplicationSlot *slot = MyReplicationSlot;
 
 	SpinLockAcquire(&slot->mutex);
 	MyPgXact->xmin = InvalidTransactionId;
@@ -1934,8 +1929,7 @@ InitWalSenderSlot(void)
 	 */
 	for (i = 0; i < max_wal_senders; i++)
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = &WalSndCtl->walsnds[i];
+		WalSnd *walsnd = &WalSndCtl->walsnds[i];
 
 		SpinLockAcquire(&walsnd->mutex);
 
@@ -2145,8 +2139,7 @@ retry:
 	 */
 	if (am_cascading_walsender)
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = MyWalSnd;
+		WalSnd *walsnd = MyWalSnd;
 		bool		reload;
 
 		SpinLockAcquire(&walsnd->mutex);
@@ -2384,8 +2377,7 @@ XLogSendPhysical(void)
 
 	/* Update shared memory status */
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = MyWalSnd;
+		WalSnd *walsnd = MyWalSnd;
 
 		SpinLockAcquire(&walsnd->mutex);
 		walsnd->sentPtr = sentPtr;
@@ -2447,8 +2439,7 @@ XLogSendLogical(void)
 
 	/* Update shared memory status */
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = MyWalSnd;
+		WalSnd *walsnd = MyWalSnd;
 
 		SpinLockAcquire(&walsnd->mutex);
 		walsnd->sentPtr = sentPtr;
@@ -2539,8 +2530,7 @@ WalSndRqstFileReload(void)
 
 	for (i = 0; i < max_wal_senders; i++)
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = &WalSndCtl->walsnds[i];
+		WalSnd *walsnd = &WalSndCtl->walsnds[i];
 
 		if (walsnd->pid == 0)
 			continue;
@@ -2692,8 +2682,7 @@ WalSndWakeup(void)
 void
 WalSndSetState(WalSndState state)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalSnd *walsnd = MyWalSnd;
+	WalSnd *walsnd = MyWalSnd;
 
 	Assert(am_walsender);
 
@@ -2777,8 +2766,7 @@ pg_stat_get_wal_senders(PG_FUNCTION_ARGS)
 
 	for (i = 0; i < max_wal_senders; i++)
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = &WalSndCtl->walsnds[i];
+		WalSnd *walsnd = &WalSndCtl->walsnds[i];
 		XLogRecPtr	sentPtr;
 		XLogRecPtr	write;
 		XLogRecPtr	flush;
@@ -2934,8 +2922,7 @@ GetOldestWALSendPointer(void)
 
 	for (i = 0; i < max_wal_senders; i++)
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = &WalSndCtl->walsnds[i];
+		WalSnd *walsnd = &WalSndCtl->walsnds[i];
 		XLogRecPtr	recptr;
 
 		if (walsnd->pid == 0)
#2Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Thomas Munro (#1)
Re: Obsolete use of volatile in walsender.c, walreceiver.c, walreceiverfuncs.c?

Thomas Munro wrote:

In walsender.c, walreceiver.c, walreceiverfuncs.c there are several
places where volatile qualifiers are used apparently only to prevent
reordering around spinlock operations.

In replication/slot.c there are a number of places (12, I think) that
introduce a block specifically to contain a volatile cast on a variable
for spinlock-protected access. We could remove the whole thing and save
at least 3 lines and one indentation level for each of them.

--
�lvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#3Thomas Munro
thomas.munro@enterprisedb.com
In reply to: Alvaro Herrera (#2)
1 attachment(s)
Re: Obsolete use of volatile in walsender.c, walreceiver.c, walreceiverfuncs.c?

On Tue, Sep 22, 2015 at 8:19 AM, Alvaro Herrera
<alvherre@2ndquadrant.com> wrote:

Thomas Munro wrote:

In walsender.c, walreceiver.c, walreceiverfuncs.c there are several
places where volatile qualifiers are used apparently only to prevent
reordering around spinlock operations.

In replication/slot.c there are a number of places (12, I think) that
introduce a block specifically to contain a volatile cast on a variable
for spinlock-protected access. We could remove the whole thing and save
at least 3 lines and one indentation level for each of them.

Right, see attached.

--
Thomas Munro
http://www.enterprisedb.com

Attachments:

replication-strip-volatile-v2.patchapplication/octet-stream; name=replication-strip-volatile-v2.patchDownload
diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c
index c66619c..5b18cb6 100644
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -288,15 +288,11 @@ ReplicationSlotCreate(const char *name, bool db_specific,
 	slot->in_use = true;
 
 	/* We can now mark the slot active, and that makes it our slot. */
-	{
-		volatile ReplicationSlot *vslot = slot;
-
-		SpinLockAcquire(&slot->mutex);
-		Assert(vslot->active_pid == 0);
-		vslot->active_pid = MyProcPid;
-		SpinLockRelease(&slot->mutex);
-		MyReplicationSlot = slot;
-	}
+	SpinLockAcquire(&slot->mutex);
+	Assert(slot->active_pid == 0);
+	slot->active_pid = MyProcPid;
+	SpinLockRelease(&slot->mutex);
+	MyReplicationSlot = slot;
 
 	LWLockRelease(ReplicationSlotControlLock);
 
@@ -329,12 +325,10 @@ ReplicationSlotAcquire(const char *name)
 
 		if (s->in_use && strcmp(name, NameStr(s->data.name)) == 0)
 		{
-			volatile ReplicationSlot *vslot = s;
-
 			SpinLockAcquire(&s->mutex);
-			active_pid = vslot->active_pid;
+			active_pid = s->active_pid;
 			if (active_pid == 0)
-				vslot->active_pid = MyProcPid;
+				s->active_pid = MyProcPid;
 			SpinLockRelease(&s->mutex);
 			slot = s;
 			break;
@@ -380,10 +374,8 @@ ReplicationSlotRelease(void)
 	else
 	{
 		/* Mark slot inactive.  We're not freeing it, just disconnecting. */
-		volatile ReplicationSlot *vslot = slot;
-
 		SpinLockAcquire(&slot->mutex);
-		vslot->active_pid = 0;
+		slot->active_pid = 0;
 		SpinLockRelease(&slot->mutex);
 	}
 
@@ -459,11 +451,10 @@ ReplicationSlotDropAcquired(void)
 	}
 	else
 	{
-		volatile ReplicationSlot *vslot = slot;
 		bool		fail_softly = slot->data.persistency == RS_EPHEMERAL;
 
 		SpinLockAcquire(&slot->mutex);
-		vslot->active_pid = 0;
+		slot->active_pid = 0;
 		SpinLockRelease(&slot->mutex);
 
 		ereport(fail_softly ? WARNING : ERROR,
@@ -533,16 +524,13 @@ ReplicationSlotSave(void)
 void
 ReplicationSlotMarkDirty(void)
 {
+	ReplicationSlot *slot = MyReplicationSlot;
 	Assert(MyReplicationSlot != NULL);
 
-	{
-		volatile ReplicationSlot *vslot = MyReplicationSlot;
-
-		SpinLockAcquire(&vslot->mutex);
-		MyReplicationSlot->just_dirtied = true;
-		MyReplicationSlot->dirty = true;
-		SpinLockRelease(&vslot->mutex);
-	}
+	SpinLockAcquire(&slot->mutex);
+	MyReplicationSlot->just_dirtied = true;
+	MyReplicationSlot->dirty = true;
+	SpinLockRelease(&slot->mutex);
 }
 
 /*
@@ -557,13 +545,9 @@ ReplicationSlotPersist(void)
 	Assert(slot != NULL);
 	Assert(slot->data.persistency != RS_PERSISTENT);
 
-	{
-		volatile ReplicationSlot *vslot = slot;
-
-		SpinLockAcquire(&slot->mutex);
-		vslot->data.persistency = RS_PERSISTENT;
-		SpinLockRelease(&slot->mutex);
-	}
+	SpinLockAcquire(&slot->mutex);
+	slot->data.persistency = RS_PERSISTENT;
+	SpinLockRelease(&slot->mutex);
 
 	ReplicationSlotMarkDirty();
 	ReplicationSlotSave();
@@ -593,14 +577,10 @@ ReplicationSlotsComputeRequiredXmin(bool already_locked)
 		if (!s->in_use)
 			continue;
 
-		{
-			volatile ReplicationSlot *vslot = s;
-
-			SpinLockAcquire(&s->mutex);
-			effective_xmin = vslot->effective_xmin;
-			effective_catalog_xmin = vslot->effective_catalog_xmin;
-			SpinLockRelease(&s->mutex);
-		}
+		SpinLockAcquire(&s->mutex);
+		effective_xmin = s->effective_xmin;
+		effective_catalog_xmin = s->effective_catalog_xmin;
+		SpinLockRelease(&s->mutex);
 
 		/* check the data xmin */
 		if (TransactionIdIsValid(effective_xmin) &&
@@ -641,13 +621,9 @@ ReplicationSlotsComputeRequiredLSN(void)
 		if (!s->in_use)
 			continue;
 
-		{
-			volatile ReplicationSlot *vslot = s;
-
-			SpinLockAcquire(&s->mutex);
-			restart_lsn = vslot->data.restart_lsn;
-			SpinLockRelease(&s->mutex);
-		}
+		SpinLockAcquire(&s->mutex);
+		restart_lsn = s->data.restart_lsn;
+		SpinLockRelease(&s->mutex);
 
 		if (restart_lsn != InvalidXLogRecPtr &&
 			(min_required == InvalidXLogRecPtr ||
@@ -684,7 +660,7 @@ ReplicationSlotsComputeLogicalRestartLSN(void)
 
 	for (i = 0; i < max_replication_slots; i++)
 	{
-		volatile ReplicationSlot *s;
+		ReplicationSlot *s;
 		XLogRecPtr	restart_lsn;
 
 		s = &ReplicationSlotCtl->replication_slots[i];
@@ -733,7 +709,7 @@ ReplicationSlotsCountDBSlots(Oid dboid, int *nslots, int *nactive)
 	LWLockAcquire(ReplicationSlotControlLock, LW_SHARED);
 	for (i = 0; i < max_replication_slots; i++)
 	{
-		volatile ReplicationSlot *s;
+		ReplicationSlot *s;
 
 		s = &ReplicationSlotCtl->replication_slots[i];
 
@@ -1023,14 +999,10 @@ SaveSlotToPath(ReplicationSlot *slot, const char *dir, int elevel)
 	bool		was_dirty;
 
 	/* first check whether there's something to write out */
-	{
-		volatile ReplicationSlot *vslot = slot;
-
-		SpinLockAcquire(&vslot->mutex);
-		was_dirty = vslot->dirty;
-		vslot->just_dirtied = false;
-		SpinLockRelease(&vslot->mutex);
-	}
+	SpinLockAcquire(&slot->mutex);
+	was_dirty = slot->dirty;
+	slot->just_dirtied = false;
+	SpinLockRelease(&slot->mutex);
 
 	/* and don't do anything if there's nothing to write */
 	if (!was_dirty)
@@ -1124,14 +1096,10 @@ SaveSlotToPath(ReplicationSlot *slot, const char *dir, int elevel)
 	 * Successfully wrote, unset dirty bit, unless somebody dirtied again
 	 * already.
 	 */
-	{
-		volatile ReplicationSlot *vslot = slot;
-
-		SpinLockAcquire(&vslot->mutex);
-		if (!vslot->just_dirtied)
-			vslot->dirty = false;
-		SpinLockRelease(&vslot->mutex);
-	}
+	SpinLockAcquire(&slot->mutex);
+	if (!slot->just_dirtied)
+		slot->dirty = false;
+	SpinLockRelease(&slot->mutex);
 
 	LWLockRelease(slot->io_in_progress_lock);
 }
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index 41e57f2..183a3a5 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -192,9 +192,7 @@ WalReceiverMain(void)
 	TimeLineID	startpointTLI;
 	TimeLineID	primaryTLI;
 	bool		first_stream;
-
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 	TimestampTz last_recv_timestamp;
 	bool		ping_sent;
 
@@ -559,8 +557,7 @@ WalReceiverMain(void)
 static void
 WalRcvWaitForStartPosition(XLogRecPtr *startpoint, TimeLineID *startpointTLI)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 	int			state;
 
 	SpinLockAcquire(&walrcv->mutex);
@@ -693,8 +690,7 @@ WalRcvFetchTimeLineHistoryFiles(TimeLineID first, TimeLineID last)
 static void
 WalRcvDie(int code, Datum arg)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 
 	/* Ensure that all WAL records received are flushed to disk */
 	XLogWalRcvFlush(true);
@@ -974,8 +970,7 @@ XLogWalRcvFlush(bool dying)
 {
 	if (LogstreamResult.Flush < LogstreamResult.Write)
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalRcvData *walrcv = WalRcv;
+		WalRcvData *walrcv = WalRcv;
 
 		issue_xlog_fsync(recvFile, recvSegNo);
 
@@ -1179,8 +1174,7 @@ XLogWalRcvSendHSFeedback(bool immed)
 static void
 ProcessWalSndrMessage(XLogRecPtr walEnd, TimestampTz sendTime)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 
 	TimestampTz lastMsgReceiptTime = GetCurrentTimestamp();
 
diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c
index f77a790..4452f25 100644
--- a/src/backend/replication/walreceiverfuncs.c
+++ b/src/backend/replication/walreceiverfuncs.c
@@ -72,8 +72,7 @@ WalRcvShmemInit(void)
 bool
 WalRcvRunning(void)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 	WalRcvState state;
 	pg_time_t	startTime;
 
@@ -118,8 +117,7 @@ WalRcvRunning(void)
 bool
 WalRcvStreaming(void)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 	WalRcvState state;
 	pg_time_t	startTime;
 
@@ -165,8 +163,7 @@ WalRcvStreaming(void)
 void
 ShutdownWalRcv(void)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 	pid_t		walrcvpid = 0;
 
 	/*
@@ -227,8 +224,7 @@ void
 RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo,
 					 const char *slotname)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 	bool		launch = false;
 	pg_time_t	now = (pg_time_t) time(NULL);
 
@@ -298,8 +294,7 @@ RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo,
 XLogRecPtr
 GetWalRcvWriteRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 	XLogRecPtr	recptr;
 
 	SpinLockAcquire(&walrcv->mutex);
@@ -320,9 +315,7 @@ GetWalRcvWriteRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI)
 int
 GetReplicationApplyDelay(void)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
-
+	WalRcvData *walrcv = WalRcv;
 	XLogRecPtr	receivePtr;
 	XLogRecPtr	replayPtr;
 
@@ -359,8 +352,7 @@ GetReplicationApplyDelay(void)
 int
 GetReplicationTransferLatency(void)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 
 	TimestampTz lastMsgSendTime;
 	TimestampTz lastMsgReceiptTime;
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index c95fe75..c6043cd 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -641,8 +641,7 @@ StartReplication(StartReplicationCmd *cmd)
 
 		/* Initialize shared memory status, too */
 		{
-			/* use volatile pointer to prevent code rearrangement */
-			volatile WalSnd *walsnd = MyWalSnd;
+			WalSnd *walsnd = MyWalSnd;
 
 			SpinLockAcquire(&walsnd->mutex);
 			walsnd->sentPtr = sentPtr;
@@ -990,8 +989,7 @@ StartLogicalReplication(StartReplicationCmd *cmd)
 
 	/* Also update the sent position status in shared memory */
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = MyWalSnd;
+		WalSnd *walsnd = MyWalSnd;
 
 		SpinLockAcquire(&walsnd->mutex);
 		walsnd->sentPtr = MyReplicationSlot->data.restart_lsn;
@@ -1494,9 +1492,7 @@ static void
 PhysicalConfirmReceivedLocation(XLogRecPtr lsn)
 {
 	bool		changed = false;
-
-	/* use volatile pointer to prevent code rearrangement */
-	volatile ReplicationSlot *slot = MyReplicationSlot;
+	ReplicationSlot *slot = MyReplicationSlot;
 
 	Assert(lsn != InvalidXLogRecPtr);
 	SpinLockAcquire(&slot->mutex);
@@ -1554,8 +1550,7 @@ ProcessStandbyReplyMessage(void)
 	 * standby.
 	 */
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = MyWalSnd;
+		WalSnd *walsnd = MyWalSnd;
 
 		SpinLockAcquire(&walsnd->mutex);
 		walsnd->write = writePtr;
@@ -1584,7 +1579,7 @@ static void
 PhysicalReplicationSlotNewXmin(TransactionId feedbackXmin)
 {
 	bool		changed = false;
-	volatile ReplicationSlot *slot = MyReplicationSlot;
+	ReplicationSlot *slot = MyReplicationSlot;
 
 	SpinLockAcquire(&slot->mutex);
 	MyPgXact->xmin = InvalidTransactionId;
@@ -1934,8 +1929,7 @@ InitWalSenderSlot(void)
 	 */
 	for (i = 0; i < max_wal_senders; i++)
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = &WalSndCtl->walsnds[i];
+		WalSnd *walsnd = &WalSndCtl->walsnds[i];
 
 		SpinLockAcquire(&walsnd->mutex);
 
@@ -2145,8 +2139,7 @@ retry:
 	 */
 	if (am_cascading_walsender)
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = MyWalSnd;
+		WalSnd *walsnd = MyWalSnd;
 		bool		reload;
 
 		SpinLockAcquire(&walsnd->mutex);
@@ -2384,8 +2377,7 @@ XLogSendPhysical(void)
 
 	/* Update shared memory status */
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = MyWalSnd;
+		WalSnd *walsnd = MyWalSnd;
 
 		SpinLockAcquire(&walsnd->mutex);
 		walsnd->sentPtr = sentPtr;
@@ -2447,8 +2439,7 @@ XLogSendLogical(void)
 
 	/* Update shared memory status */
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = MyWalSnd;
+		WalSnd *walsnd = MyWalSnd;
 
 		SpinLockAcquire(&walsnd->mutex);
 		walsnd->sentPtr = sentPtr;
@@ -2539,8 +2530,7 @@ WalSndRqstFileReload(void)
 
 	for (i = 0; i < max_wal_senders; i++)
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = &WalSndCtl->walsnds[i];
+		WalSnd *walsnd = &WalSndCtl->walsnds[i];
 
 		if (walsnd->pid == 0)
 			continue;
@@ -2692,8 +2682,7 @@ WalSndWakeup(void)
 void
 WalSndSetState(WalSndState state)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalSnd *walsnd = MyWalSnd;
+	WalSnd *walsnd = MyWalSnd;
 
 	Assert(am_walsender);
 
@@ -2777,8 +2766,7 @@ pg_stat_get_wal_senders(PG_FUNCTION_ARGS)
 
 	for (i = 0; i < max_wal_senders; i++)
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = &WalSndCtl->walsnds[i];
+		WalSnd *walsnd = &WalSndCtl->walsnds[i];
 		XLogRecPtr	sentPtr;
 		XLogRecPtr	write;
 		XLogRecPtr	flush;
@@ -2934,8 +2922,7 @@ GetOldestWALSendPointer(void)
 
 	for (i = 0; i < max_wal_senders; i++)
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = &WalSndCtl->walsnds[i];
+		WalSnd *walsnd = &WalSndCtl->walsnds[i];
 		XLogRecPtr	recptr;
 
 		if (walsnd->pid == 0)
#4Andres Freund
andres@anarazel.de
In reply to: Thomas Munro (#1)
Re: Obsolete use of volatile in walsender.c, walreceiver.c, walreceiverfuncs.c?

Hi,

On 2015-09-17 16:32:17 +1200, Thomas Munro wrote:

In walsender.c, walreceiver.c, walreceiverfuncs.c there are several
places where volatile qualifiers are used apparently only to prevent
reordering around spinlock operations. My understanding is that if
potential load/store reordering around spinlock operations is the only
reason for using volatile, 0709b7ee72e4bc71ad07b7120acd117265ab51d0
made it unnecessary. For example see
6ba4ecbf477e0b25dd7bde1b0c4e07fc2da19348 which stripped some volatile
qualifiers out of xlog.c.

Same in bufmgr.c et al. There it's actually rather annoying for new code
because volatile needs to be casted away in a bunch of places...

Greetings,

Andres Freund

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#5Michael Paquier
michael.paquier@gmail.com
In reply to: Thomas Munro (#3)
2 attachment(s)
Re: Obsolete use of volatile in walsender.c, walreceiver.c, walreceiverfuncs.c?

On Tue, Sep 22, 2015 at 7:25 AM, Thomas Munro
<thomas.munro@enterprisedb.com> wrote:

On Tue, Sep 22, 2015 at 8:19 AM, Alvaro Herrera
<alvherre@2ndquadrant.com> wrote:

Thomas Munro wrote:

In walsender.c, walreceiver.c, walreceiverfuncs.c there are several
places where volatile qualifiers are used apparently only to prevent
reordering around spinlock operations.

In replication/slot.c there are a number of places (12, I think) that
introduce a block specifically to contain a volatile cast on a variable
for spinlock-protected access. We could remove the whole thing and save
at least 3 lines and one indentation level for each of them.

Right, see attached.

It seems to me that we could as well simplify checkpoint.c and
logical.c. In those files volatile casts are used as well to protect
from reordering for spinlock operations. See for example 0002 on top
of 0001 that is Thomas' patch.
--
Michael

Attachments:

0001-Remove-obsolete-use-of-volatile-in-WAL-related-files.patchtext/x-patch; charset=US-ASCII; name=0001-Remove-obsolete-use-of-volatile-in-WAL-related-files.patchDownload
From 929db46e249ac3f6e587b38aff8ba4468e7d776d Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@otacoo.com>
Date: Fri, 2 Oct 2015 10:57:15 +0900
Subject: [PATCH 1/2] Remove obsolete use of volatile in WAL-related files

Patch by Thomas Munro.
---
 src/backend/replication/slot.c             | 100 ++++++++++-------------------
 src/backend/replication/walreceiver.c      |  16 ++---
 src/backend/replication/walreceiverfuncs.c |  22 ++-----
 src/backend/replication/walsender.c        |  39 ++++-------
 4 files changed, 59 insertions(+), 118 deletions(-)

diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c
index c66619c..5b18cb6 100644
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -288,15 +288,11 @@ ReplicationSlotCreate(const char *name, bool db_specific,
 	slot->in_use = true;
 
 	/* We can now mark the slot active, and that makes it our slot. */
-	{
-		volatile ReplicationSlot *vslot = slot;
-
-		SpinLockAcquire(&slot->mutex);
-		Assert(vslot->active_pid == 0);
-		vslot->active_pid = MyProcPid;
-		SpinLockRelease(&slot->mutex);
-		MyReplicationSlot = slot;
-	}
+	SpinLockAcquire(&slot->mutex);
+	Assert(slot->active_pid == 0);
+	slot->active_pid = MyProcPid;
+	SpinLockRelease(&slot->mutex);
+	MyReplicationSlot = slot;
 
 	LWLockRelease(ReplicationSlotControlLock);
 
@@ -329,12 +325,10 @@ ReplicationSlotAcquire(const char *name)
 
 		if (s->in_use && strcmp(name, NameStr(s->data.name)) == 0)
 		{
-			volatile ReplicationSlot *vslot = s;
-
 			SpinLockAcquire(&s->mutex);
-			active_pid = vslot->active_pid;
+			active_pid = s->active_pid;
 			if (active_pid == 0)
-				vslot->active_pid = MyProcPid;
+				s->active_pid = MyProcPid;
 			SpinLockRelease(&s->mutex);
 			slot = s;
 			break;
@@ -380,10 +374,8 @@ ReplicationSlotRelease(void)
 	else
 	{
 		/* Mark slot inactive.  We're not freeing it, just disconnecting. */
-		volatile ReplicationSlot *vslot = slot;
-
 		SpinLockAcquire(&slot->mutex);
-		vslot->active_pid = 0;
+		slot->active_pid = 0;
 		SpinLockRelease(&slot->mutex);
 	}
 
@@ -459,11 +451,10 @@ ReplicationSlotDropAcquired(void)
 	}
 	else
 	{
-		volatile ReplicationSlot *vslot = slot;
 		bool		fail_softly = slot->data.persistency == RS_EPHEMERAL;
 
 		SpinLockAcquire(&slot->mutex);
-		vslot->active_pid = 0;
+		slot->active_pid = 0;
 		SpinLockRelease(&slot->mutex);
 
 		ereport(fail_softly ? WARNING : ERROR,
@@ -533,16 +524,13 @@ ReplicationSlotSave(void)
 void
 ReplicationSlotMarkDirty(void)
 {
+	ReplicationSlot *slot = MyReplicationSlot;
 	Assert(MyReplicationSlot != NULL);
 
-	{
-		volatile ReplicationSlot *vslot = MyReplicationSlot;
-
-		SpinLockAcquire(&vslot->mutex);
-		MyReplicationSlot->just_dirtied = true;
-		MyReplicationSlot->dirty = true;
-		SpinLockRelease(&vslot->mutex);
-	}
+	SpinLockAcquire(&slot->mutex);
+	MyReplicationSlot->just_dirtied = true;
+	MyReplicationSlot->dirty = true;
+	SpinLockRelease(&slot->mutex);
 }
 
 /*
@@ -557,13 +545,9 @@ ReplicationSlotPersist(void)
 	Assert(slot != NULL);
 	Assert(slot->data.persistency != RS_PERSISTENT);
 
-	{
-		volatile ReplicationSlot *vslot = slot;
-
-		SpinLockAcquire(&slot->mutex);
-		vslot->data.persistency = RS_PERSISTENT;
-		SpinLockRelease(&slot->mutex);
-	}
+	SpinLockAcquire(&slot->mutex);
+	slot->data.persistency = RS_PERSISTENT;
+	SpinLockRelease(&slot->mutex);
 
 	ReplicationSlotMarkDirty();
 	ReplicationSlotSave();
@@ -593,14 +577,10 @@ ReplicationSlotsComputeRequiredXmin(bool already_locked)
 		if (!s->in_use)
 			continue;
 
-		{
-			volatile ReplicationSlot *vslot = s;
-
-			SpinLockAcquire(&s->mutex);
-			effective_xmin = vslot->effective_xmin;
-			effective_catalog_xmin = vslot->effective_catalog_xmin;
-			SpinLockRelease(&s->mutex);
-		}
+		SpinLockAcquire(&s->mutex);
+		effective_xmin = s->effective_xmin;
+		effective_catalog_xmin = s->effective_catalog_xmin;
+		SpinLockRelease(&s->mutex);
 
 		/* check the data xmin */
 		if (TransactionIdIsValid(effective_xmin) &&
@@ -641,13 +621,9 @@ ReplicationSlotsComputeRequiredLSN(void)
 		if (!s->in_use)
 			continue;
 
-		{
-			volatile ReplicationSlot *vslot = s;
-
-			SpinLockAcquire(&s->mutex);
-			restart_lsn = vslot->data.restart_lsn;
-			SpinLockRelease(&s->mutex);
-		}
+		SpinLockAcquire(&s->mutex);
+		restart_lsn = s->data.restart_lsn;
+		SpinLockRelease(&s->mutex);
 
 		if (restart_lsn != InvalidXLogRecPtr &&
 			(min_required == InvalidXLogRecPtr ||
@@ -684,7 +660,7 @@ ReplicationSlotsComputeLogicalRestartLSN(void)
 
 	for (i = 0; i < max_replication_slots; i++)
 	{
-		volatile ReplicationSlot *s;
+		ReplicationSlot *s;
 		XLogRecPtr	restart_lsn;
 
 		s = &ReplicationSlotCtl->replication_slots[i];
@@ -733,7 +709,7 @@ ReplicationSlotsCountDBSlots(Oid dboid, int *nslots, int *nactive)
 	LWLockAcquire(ReplicationSlotControlLock, LW_SHARED);
 	for (i = 0; i < max_replication_slots; i++)
 	{
-		volatile ReplicationSlot *s;
+		ReplicationSlot *s;
 
 		s = &ReplicationSlotCtl->replication_slots[i];
 
@@ -1023,14 +999,10 @@ SaveSlotToPath(ReplicationSlot *slot, const char *dir, int elevel)
 	bool		was_dirty;
 
 	/* first check whether there's something to write out */
-	{
-		volatile ReplicationSlot *vslot = slot;
-
-		SpinLockAcquire(&vslot->mutex);
-		was_dirty = vslot->dirty;
-		vslot->just_dirtied = false;
-		SpinLockRelease(&vslot->mutex);
-	}
+	SpinLockAcquire(&slot->mutex);
+	was_dirty = slot->dirty;
+	slot->just_dirtied = false;
+	SpinLockRelease(&slot->mutex);
 
 	/* and don't do anything if there's nothing to write */
 	if (!was_dirty)
@@ -1124,14 +1096,10 @@ SaveSlotToPath(ReplicationSlot *slot, const char *dir, int elevel)
 	 * Successfully wrote, unset dirty bit, unless somebody dirtied again
 	 * already.
 	 */
-	{
-		volatile ReplicationSlot *vslot = slot;
-
-		SpinLockAcquire(&vslot->mutex);
-		if (!vslot->just_dirtied)
-			vslot->dirty = false;
-		SpinLockRelease(&vslot->mutex);
-	}
+	SpinLockAcquire(&slot->mutex);
+	if (!slot->just_dirtied)
+		slot->dirty = false;
+	SpinLockRelease(&slot->mutex);
 
 	LWLockRelease(slot->io_in_progress_lock);
 }
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index 41e57f2..183a3a5 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -192,9 +192,7 @@ WalReceiverMain(void)
 	TimeLineID	startpointTLI;
 	TimeLineID	primaryTLI;
 	bool		first_stream;
-
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 	TimestampTz last_recv_timestamp;
 	bool		ping_sent;
 
@@ -559,8 +557,7 @@ WalReceiverMain(void)
 static void
 WalRcvWaitForStartPosition(XLogRecPtr *startpoint, TimeLineID *startpointTLI)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 	int			state;
 
 	SpinLockAcquire(&walrcv->mutex);
@@ -693,8 +690,7 @@ WalRcvFetchTimeLineHistoryFiles(TimeLineID first, TimeLineID last)
 static void
 WalRcvDie(int code, Datum arg)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 
 	/* Ensure that all WAL records received are flushed to disk */
 	XLogWalRcvFlush(true);
@@ -974,8 +970,7 @@ XLogWalRcvFlush(bool dying)
 {
 	if (LogstreamResult.Flush < LogstreamResult.Write)
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalRcvData *walrcv = WalRcv;
+		WalRcvData *walrcv = WalRcv;
 
 		issue_xlog_fsync(recvFile, recvSegNo);
 
@@ -1179,8 +1174,7 @@ XLogWalRcvSendHSFeedback(bool immed)
 static void
 ProcessWalSndrMessage(XLogRecPtr walEnd, TimestampTz sendTime)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 
 	TimestampTz lastMsgReceiptTime = GetCurrentTimestamp();
 
diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c
index f77a790..4452f25 100644
--- a/src/backend/replication/walreceiverfuncs.c
+++ b/src/backend/replication/walreceiverfuncs.c
@@ -72,8 +72,7 @@ WalRcvShmemInit(void)
 bool
 WalRcvRunning(void)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 	WalRcvState state;
 	pg_time_t	startTime;
 
@@ -118,8 +117,7 @@ WalRcvRunning(void)
 bool
 WalRcvStreaming(void)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 	WalRcvState state;
 	pg_time_t	startTime;
 
@@ -165,8 +163,7 @@ WalRcvStreaming(void)
 void
 ShutdownWalRcv(void)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 	pid_t		walrcvpid = 0;
 
 	/*
@@ -227,8 +224,7 @@ void
 RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo,
 					 const char *slotname)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 	bool		launch = false;
 	pg_time_t	now = (pg_time_t) time(NULL);
 
@@ -298,8 +294,7 @@ RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo,
 XLogRecPtr
 GetWalRcvWriteRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 	XLogRecPtr	recptr;
 
 	SpinLockAcquire(&walrcv->mutex);
@@ -320,9 +315,7 @@ GetWalRcvWriteRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI)
 int
 GetReplicationApplyDelay(void)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
-
+	WalRcvData *walrcv = WalRcv;
 	XLogRecPtr	receivePtr;
 	XLogRecPtr	replayPtr;
 
@@ -359,8 +352,7 @@ GetReplicationApplyDelay(void)
 int
 GetReplicationTransferLatency(void)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalRcvData *walrcv = WalRcv;
+	WalRcvData *walrcv = WalRcv;
 
 	TimestampTz lastMsgSendTime;
 	TimestampTz lastMsgReceiptTime;
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index c95fe75..c6043cd 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -641,8 +641,7 @@ StartReplication(StartReplicationCmd *cmd)
 
 		/* Initialize shared memory status, too */
 		{
-			/* use volatile pointer to prevent code rearrangement */
-			volatile WalSnd *walsnd = MyWalSnd;
+			WalSnd *walsnd = MyWalSnd;
 
 			SpinLockAcquire(&walsnd->mutex);
 			walsnd->sentPtr = sentPtr;
@@ -990,8 +989,7 @@ StartLogicalReplication(StartReplicationCmd *cmd)
 
 	/* Also update the sent position status in shared memory */
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = MyWalSnd;
+		WalSnd *walsnd = MyWalSnd;
 
 		SpinLockAcquire(&walsnd->mutex);
 		walsnd->sentPtr = MyReplicationSlot->data.restart_lsn;
@@ -1494,9 +1492,7 @@ static void
 PhysicalConfirmReceivedLocation(XLogRecPtr lsn)
 {
 	bool		changed = false;
-
-	/* use volatile pointer to prevent code rearrangement */
-	volatile ReplicationSlot *slot = MyReplicationSlot;
+	ReplicationSlot *slot = MyReplicationSlot;
 
 	Assert(lsn != InvalidXLogRecPtr);
 	SpinLockAcquire(&slot->mutex);
@@ -1554,8 +1550,7 @@ ProcessStandbyReplyMessage(void)
 	 * standby.
 	 */
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = MyWalSnd;
+		WalSnd *walsnd = MyWalSnd;
 
 		SpinLockAcquire(&walsnd->mutex);
 		walsnd->write = writePtr;
@@ -1584,7 +1579,7 @@ static void
 PhysicalReplicationSlotNewXmin(TransactionId feedbackXmin)
 {
 	bool		changed = false;
-	volatile ReplicationSlot *slot = MyReplicationSlot;
+	ReplicationSlot *slot = MyReplicationSlot;
 
 	SpinLockAcquire(&slot->mutex);
 	MyPgXact->xmin = InvalidTransactionId;
@@ -1934,8 +1929,7 @@ InitWalSenderSlot(void)
 	 */
 	for (i = 0; i < max_wal_senders; i++)
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = &WalSndCtl->walsnds[i];
+		WalSnd *walsnd = &WalSndCtl->walsnds[i];
 
 		SpinLockAcquire(&walsnd->mutex);
 
@@ -2145,8 +2139,7 @@ retry:
 	 */
 	if (am_cascading_walsender)
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = MyWalSnd;
+		WalSnd *walsnd = MyWalSnd;
 		bool		reload;
 
 		SpinLockAcquire(&walsnd->mutex);
@@ -2384,8 +2377,7 @@ XLogSendPhysical(void)
 
 	/* Update shared memory status */
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = MyWalSnd;
+		WalSnd *walsnd = MyWalSnd;
 
 		SpinLockAcquire(&walsnd->mutex);
 		walsnd->sentPtr = sentPtr;
@@ -2447,8 +2439,7 @@ XLogSendLogical(void)
 
 	/* Update shared memory status */
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = MyWalSnd;
+		WalSnd *walsnd = MyWalSnd;
 
 		SpinLockAcquire(&walsnd->mutex);
 		walsnd->sentPtr = sentPtr;
@@ -2539,8 +2530,7 @@ WalSndRqstFileReload(void)
 
 	for (i = 0; i < max_wal_senders; i++)
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = &WalSndCtl->walsnds[i];
+		WalSnd *walsnd = &WalSndCtl->walsnds[i];
 
 		if (walsnd->pid == 0)
 			continue;
@@ -2692,8 +2682,7 @@ WalSndWakeup(void)
 void
 WalSndSetState(WalSndState state)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile WalSnd *walsnd = MyWalSnd;
+	WalSnd *walsnd = MyWalSnd;
 
 	Assert(am_walsender);
 
@@ -2777,8 +2766,7 @@ pg_stat_get_wal_senders(PG_FUNCTION_ARGS)
 
 	for (i = 0; i < max_wal_senders; i++)
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = &WalSndCtl->walsnds[i];
+		WalSnd *walsnd = &WalSndCtl->walsnds[i];
 		XLogRecPtr	sentPtr;
 		XLogRecPtr	write;
 		XLogRecPtr	flush;
@@ -2934,8 +2922,7 @@ GetOldestWALSendPointer(void)
 
 	for (i = 0; i < max_wal_senders; i++)
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile WalSnd *walsnd = &WalSndCtl->walsnds[i];
+		WalSnd *walsnd = &WalSndCtl->walsnds[i];
 		XLogRecPtr	recptr;
 
 		if (walsnd->pid == 0)
-- 
2.6.0

0002-Remove-use-of-volatile-for-spinlock-operations-in-mo.patchtext/x-patch; charset=US-ASCII; name=0002-Remove-use-of-volatile-for-spinlock-operations-in-mo.patchDownload
From db26450da5814f2c73180c3b5f553971985b2ffa Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@otacoo.com>
Date: Fri, 2 Oct 2015 11:59:55 +0900
Subject: [PATCH 2/2] Remove use of volatile for spinlock operations in more
 places

---
 src/backend/postmaster/checkpointer.c     | 64 +++++++++++++------------------
 src/backend/replication/logical/logical.c | 49 +++++++++++------------
 2 files changed, 49 insertions(+), 64 deletions(-)

diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index 3b3a09e..dc5b856 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -288,13 +288,10 @@ CheckpointerMain(void)
 		/* Warn any waiting backends that the checkpoint failed. */
 		if (ckpt_active)
 		{
-			/* use volatile pointer to prevent code rearrangement */
-			volatile CheckpointerShmemStruct *cps = CheckpointerShmem;
-
-			SpinLockAcquire(&cps->ckpt_lck);
-			cps->ckpt_failed++;
-			cps->ckpt_done = cps->ckpt_started;
-			SpinLockRelease(&cps->ckpt_lck);
+			SpinLockAcquire(&CheckpointerShmem->ckpt_lck);
+			CheckpointerShmem->ckpt_failed++;
+			CheckpointerShmem->ckpt_done = CheckpointerShmem->ckpt_started;
+			SpinLockRelease(&CheckpointerShmem->ckpt_lck);
 
 			ckpt_active = false;
 		}
@@ -428,9 +425,6 @@ CheckpointerMain(void)
 			bool		ckpt_performed = false;
 			bool		do_restartpoint;
 
-			/* use volatile pointer to prevent code rearrangement */
-			volatile CheckpointerShmemStruct *cps = CheckpointerShmem;
-
 			/*
 			 * Check if we should perform a checkpoint or a restartpoint. As a
 			 * side-effect, RecoveryInProgress() initializes TimeLineID if
@@ -443,11 +437,11 @@ CheckpointerMain(void)
 			 * checkpoint we should perform, and increase the started-counter
 			 * to acknowledge that we've started a new checkpoint.
 			 */
-			SpinLockAcquire(&cps->ckpt_lck);
-			flags |= cps->ckpt_flags;
-			cps->ckpt_flags = 0;
-			cps->ckpt_started++;
-			SpinLockRelease(&cps->ckpt_lck);
+			SpinLockAcquire(&CheckpointerShmem->ckpt_lck);
+			flags |= CheckpointerShmem->ckpt_flags;
+			CheckpointerShmem->ckpt_flags = 0;
+			CheckpointerShmem->ckpt_started++;
+			SpinLockRelease(&CheckpointerShmem->ckpt_lck);
 
 			/*
 			 * The end-of-recovery checkpoint is a real checkpoint that's
@@ -505,9 +499,9 @@ CheckpointerMain(void)
 			/*
 			 * Indicate checkpoint completion to any waiting backends.
 			 */
-			SpinLockAcquire(&cps->ckpt_lck);
-			cps->ckpt_done = cps->ckpt_started;
-			SpinLockRelease(&cps->ckpt_lck);
+			SpinLockAcquire(&CheckpointerShmem->ckpt_lck);
+			CheckpointerShmem->ckpt_done = CheckpointerShmem->ckpt_started;
+			SpinLockRelease(&CheckpointerShmem->ckpt_lck);
 
 			if (ckpt_performed)
 			{
@@ -957,8 +951,6 @@ CheckpointerShmemInit(void)
 void
 RequestCheckpoint(int flags)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile CheckpointerShmemStruct *cps = CheckpointerShmem;
 	int			ntries;
 	int			old_failed,
 				old_started;
@@ -992,13 +984,13 @@ RequestCheckpoint(int flags)
 	 * a "stronger" request by another backend.  The flag senses must be
 	 * chosen to make this work!
 	 */
-	SpinLockAcquire(&cps->ckpt_lck);
+	SpinLockAcquire(&CheckpointerShmem->ckpt_lck);
 
-	old_failed = cps->ckpt_failed;
-	old_started = cps->ckpt_started;
-	cps->ckpt_flags |= flags;
+	old_failed = CheckpointerShmem->ckpt_failed;
+	old_started = CheckpointerShmem->ckpt_started;
+	CheckpointerShmem->ckpt_flags |= flags;
 
-	SpinLockRelease(&cps->ckpt_lck);
+	SpinLockRelease(&CheckpointerShmem->ckpt_lck);
 
 	/*
 	 * Send signal to request checkpoint.  It's possible that the checkpointer
@@ -1046,9 +1038,9 @@ RequestCheckpoint(int flags)
 		/* Wait for a new checkpoint to start. */
 		for (;;)
 		{
-			SpinLockAcquire(&cps->ckpt_lck);
-			new_started = cps->ckpt_started;
-			SpinLockRelease(&cps->ckpt_lck);
+			SpinLockAcquire(&CheckpointerShmem->ckpt_lck);
+			new_started = CheckpointerShmem->ckpt_started;
+			SpinLockRelease(&CheckpointerShmem->ckpt_lck);
 
 			if (new_started != old_started)
 				break;
@@ -1064,10 +1056,10 @@ RequestCheckpoint(int flags)
 		{
 			int			new_done;
 
-			SpinLockAcquire(&cps->ckpt_lck);
-			new_done = cps->ckpt_done;
-			new_failed = cps->ckpt_failed;
-			SpinLockRelease(&cps->ckpt_lck);
+			SpinLockAcquire(&CheckpointerShmem->ckpt_lck);
+			new_done = CheckpointerShmem->ckpt_done;
+			new_failed = CheckpointerShmem->ckpt_failed;
+			SpinLockRelease(&CheckpointerShmem->ckpt_lck);
 
 			if (new_done - new_started >= 0)
 				break;
@@ -1368,15 +1360,13 @@ UpdateSharedMemoryConfig(void)
 bool
 FirstCallSinceLastCheckpoint(void)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile CheckpointerShmemStruct *cps = CheckpointerShmem;
 	static int	ckpt_done = 0;
 	int			new_done;
 	bool		FirstCall = false;
 
-	SpinLockAcquire(&cps->ckpt_lck);
-	new_done = cps->ckpt_done;
-	SpinLockRelease(&cps->ckpt_lck);
+	SpinLockAcquire(&CheckpointerShmem->ckpt_lck);
+	new_done = CheckpointerShmem->ckpt_done;
+	SpinLockRelease(&CheckpointerShmem->ckpt_lck);
 
 	if (new_done != ckpt_done)
 		FirstCall = true;
diff --git a/src/backend/replication/logical/logical.c b/src/backend/replication/logical/logical.c
index 5a07e1d..1ce9081 100644
--- a/src/backend/replication/logical/logical.c
+++ b/src/backend/replication/logical/logical.c
@@ -848,16 +848,13 @@ LogicalConfirmReceivedLocation(XLogRecPtr lsn)
 		bool		updated_xmin = false;
 		bool		updated_restart = false;
 
-		/* use volatile pointer to prevent code rearrangement */
-		volatile ReplicationSlot *slot = MyReplicationSlot;
+		SpinLockAcquire(&MyReplicationSlot->mutex);
 
-		SpinLockAcquire(&slot->mutex);
-
-		slot->data.confirmed_flush = lsn;
+		MyReplicationSlot->data.confirmed_flush = lsn;
 
 		/* if were past the location required for bumping xmin, do so */
-		if (slot->candidate_xmin_lsn != InvalidXLogRecPtr &&
-			slot->candidate_xmin_lsn <= lsn)
+		if (MyReplicationSlot->candidate_xmin_lsn != InvalidXLogRecPtr &&
+			MyReplicationSlot->candidate_xmin_lsn <= lsn)
 		{
 			/*
 			 * We have to write the changed xmin to disk *before* we change
@@ -868,28 +865,28 @@ LogicalConfirmReceivedLocation(XLogRecPtr lsn)
 			 * ->effective_xmin once the new state is synced to disk. After a
 			 * crash ->effective_xmin is set to ->xmin.
 			 */
-			if (TransactionIdIsValid(slot->candidate_catalog_xmin) &&
-				slot->data.catalog_xmin != slot->candidate_catalog_xmin)
+			if (TransactionIdIsValid(MyReplicationSlot->candidate_catalog_xmin) &&
+				MyReplicationSlot->data.catalog_xmin != MyReplicationSlot->candidate_catalog_xmin)
 			{
-				slot->data.catalog_xmin = slot->candidate_catalog_xmin;
-				slot->candidate_catalog_xmin = InvalidTransactionId;
-				slot->candidate_xmin_lsn = InvalidXLogRecPtr;
+				MyReplicationSlot->data.catalog_xmin = MyReplicationSlot->candidate_catalog_xmin;
+				MyReplicationSlot->candidate_catalog_xmin = InvalidTransactionId;
+				MyReplicationSlot->candidate_xmin_lsn = InvalidXLogRecPtr;
 				updated_xmin = true;
 			}
 		}
 
-		if (slot->candidate_restart_valid != InvalidXLogRecPtr &&
-			slot->candidate_restart_valid <= lsn)
+		if (MyReplicationSlot->candidate_restart_valid != InvalidXLogRecPtr &&
+			MyReplicationSlot->candidate_restart_valid <= lsn)
 		{
-			Assert(slot->candidate_restart_lsn != InvalidXLogRecPtr);
+			Assert(MyReplicationSlot->candidate_restart_lsn != InvalidXLogRecPtr);
 
-			slot->data.restart_lsn = slot->candidate_restart_lsn;
-			slot->candidate_restart_lsn = InvalidXLogRecPtr;
-			slot->candidate_restart_valid = InvalidXLogRecPtr;
+			MyReplicationSlot->data.restart_lsn = MyReplicationSlot->candidate_restart_lsn;
+			MyReplicationSlot->candidate_restart_lsn = InvalidXLogRecPtr;
+			MyReplicationSlot->candidate_restart_valid = InvalidXLogRecPtr;
 			updated_restart = true;
 		}
 
-		SpinLockRelease(&slot->mutex);
+		SpinLockRelease(&MyReplicationSlot->mutex);
 
 		/* first write new xmin to disk, so we know whats up after a crash */
 		if (updated_xmin || updated_restart)
@@ -907,9 +904,9 @@ LogicalConfirmReceivedLocation(XLogRecPtr lsn)
 		 */
 		if (updated_xmin)
 		{
-			SpinLockAcquire(&slot->mutex);
-			slot->effective_catalog_xmin = slot->data.catalog_xmin;
-			SpinLockRelease(&slot->mutex);
+			SpinLockAcquire(&MyReplicationSlot->mutex);
+			MyReplicationSlot->effective_catalog_xmin = MyReplicationSlot->data.catalog_xmin;
+			SpinLockRelease(&MyReplicationSlot->mutex);
 
 			ReplicationSlotsComputeRequiredXmin(false);
 			ReplicationSlotsComputeRequiredLSN();
@@ -917,10 +914,8 @@ LogicalConfirmReceivedLocation(XLogRecPtr lsn)
 	}
 	else
 	{
-		volatile ReplicationSlot *slot = MyReplicationSlot;
-
-		SpinLockAcquire(&slot->mutex);
-		slot->data.confirmed_flush = lsn;
-		SpinLockRelease(&slot->mutex);
+		SpinLockAcquire(&MyReplicationSlot->mutex);
+		MyReplicationSlot->data.confirmed_flush = lsn;
+		SpinLockRelease(&MyReplicationSlot->mutex);
 	}
 }
-- 
2.6.0

#6Robert Haas
robertmhaas@gmail.com
In reply to: Michael Paquier (#5)
Re: Obsolete use of volatile in walsender.c, walreceiver.c, walreceiverfuncs.c?

On Thu, Oct 1, 2015 at 11:01 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:

Right, see attached.

It seems to me that we could as well simplify checkpoint.c and
logical.c. In those files volatile casts are used as well to protect
from reordering for spinlock operations. See for example 0002 on top
of 0001 that is Thomas' patch.

These patches look good to me, so I have committed them.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#7Thomas Munro
thomas.munro@enterprisedb.com
In reply to: Robert Haas (#6)
3 attachment(s)
Re: Obsolete use of volatile in walsender.c, walreceiver.c, walreceiverfuncs.c?

On Wed, Oct 7, 2015 at 8:52 AM, Robert Haas <robertmhaas@gmail.com> wrote:

On Thu, Oct 1, 2015 at 11:01 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:

Right, see attached.

It seems to me that we could as well simplify checkpoint.c and
logical.c. In those files volatile casts are used as well to protect
from reordering for spinlock operations. See for example 0002 on top
of 0001 that is Thomas' patch.

These patches look good to me, so I have committed them.

Thanks. Also, spin.h's comment contains an out of date warning about
this. Here's a suggested fix for that, and a couple more volatrivia
patches.

--
Thomas Munro
http://www.enterprisedb.com

Attachments:

spin-header-comment.patchapplication/octet-stream; name=spin-header-comment.patchDownload
diff --git a/src/include/storage/spin.h b/src/include/storage/spin.h
index dc6856e..4674f48 100644
--- a/src/include/storage/spin.h
+++ b/src/include/storage/spin.h
@@ -25,15 +25,10 @@
  *	Callers must beware that the macro argument may be evaluated multiple
  *	times!
  *
- *	CAUTION: Care must be taken to ensure that loads and stores of
- *	shared memory values are not rearranged around spinlock acquire
- *	and release. This is done using the "volatile" qualifier: the C
- *	standard states that loads and stores of volatile objects cannot
- *	be rearranged *with respect to other volatile objects*. The
- *	spinlock is always written through a volatile pointer by the
- *	spinlock macros, but this is not sufficient by itself: code that
- *	protects shared data with a spinlock MUST reference that shared
- *	data through a volatile pointer.
+ *	Load and store operations in calling code are guaranteed not to be
+ *	reordered with respect to these operations, because they include a
+ *	compiler barrier.  (Before PostgreSQL 9.5, callers needed to use a
+ *	volatile qualifier to access data protected by spinlocks.)
  *
  *	Keep in mind the coding rule that spinlocks must not be held for more
  *	than a few instructions.  In particular, we assume it is not possible
strip-volatile-hash.patchapplication/octet-stream; name=strip-volatile-hash.patchDownload
diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c
index 27580af..eacffc4 100644
--- a/src/backend/utils/hash/dynahash.c
+++ b/src/backend/utils/hash/dynahash.c
@@ -941,25 +941,22 @@ hash_search_with_hash_value(HTAB *hashp,
 		case HASH_REMOVE:
 			if (currBucket != NULL)
 			{
-				/* use volatile pointer to prevent code rearrangement */
-				volatile HASHHDR *hctlv = hctl;
-
 				/* if partitioned, must lock to touch nentries and freeList */
-				if (IS_PARTITIONED(hctlv))
-					SpinLockAcquire(&hctlv->mutex);
+				if (IS_PARTITIONED(hctl))
+					SpinLockAcquire(&hctl->mutex);
 
-				Assert(hctlv->nentries > 0);
-				hctlv->nentries--;
+				Assert(hctl->nentries > 0);
+				hctl->nentries--;
 
 				/* remove record from hash bucket's chain. */
 				*prevBucketPtr = currBucket->link;
 
 				/* add the record to the freelist for this table.  */
-				currBucket->link = hctlv->freeList;
-				hctlv->freeList = currBucket;
+				currBucket->link = hctl->freeList;
+				hctl->freeList = currBucket;
 
-				if (IS_PARTITIONED(hctlv))
-					SpinLockRelease(&hctlv->mutex);
+				if (IS_PARTITIONED(hctl))
+					SpinLockRelease(&hctl->mutex);
 
 				/*
 				 * better hope the caller is synchronizing access to this
@@ -1180,26 +1177,25 @@ hash_update_hash_key(HTAB *hashp,
 static HASHBUCKET
 get_hash_entry(HTAB *hashp)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile HASHHDR *hctlv = hashp->hctl;
+	HASHHDR *hctl = hashp->hctl;
 	HASHBUCKET	newElement;
 
 	for (;;)
 	{
 		/* if partitioned, must lock to touch nentries and freeList */
-		if (IS_PARTITIONED(hctlv))
-			SpinLockAcquire(&hctlv->mutex);
+		if (IS_PARTITIONED(hctl))
+			SpinLockAcquire(&hctl->mutex);
 
 		/* try to get an entry from the freelist */
-		newElement = hctlv->freeList;
+		newElement = hctl->freeList;
 		if (newElement != NULL)
 			break;
 
 		/* no free elements.  allocate another chunk of buckets */
-		if (IS_PARTITIONED(hctlv))
-			SpinLockRelease(&hctlv->mutex);
+		if (IS_PARTITIONED(hctl))
+			SpinLockRelease(&hctl->mutex);
 
-		if (!element_alloc(hashp, hctlv->nelem_alloc))
+		if (!element_alloc(hashp, hctl->nelem_alloc))
 		{
 			/* out of memory */
 			return NULL;
@@ -1207,11 +1203,11 @@ get_hash_entry(HTAB *hashp)
 	}
 
 	/* remove entry from freelist, bump nentries */
-	hctlv->freeList = newElement->link;
-	hctlv->nentries++;
+	hctl->freeList = newElement->link;
+	hctl->nentries++;
 
-	if (IS_PARTITIONED(hctlv))
-		SpinLockRelease(&hctlv->mutex);
+	if (IS_PARTITIONED(hctl))
+		SpinLockRelease(&hctl->mutex);
 
 	return newElement;
 }
@@ -1536,8 +1532,7 @@ seg_alloc(HTAB *hashp)
 static bool
 element_alloc(HTAB *hashp, int nelem)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile HASHHDR *hctlv = hashp->hctl;
+	HASHHDR *hctl = hashp->hctl;
 	Size		elementSize;
 	HASHELEMENT *firstElement;
 	HASHELEMENT *tmpElement;
@@ -1548,7 +1543,7 @@ element_alloc(HTAB *hashp, int nelem)
 		return false;
 
 	/* Each element has a HASHELEMENT header plus user data. */
-	elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(hctlv->entrysize);
+	elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(hctl->entrysize);
 
 	CurrentDynaHashCxt = hashp->hcxt;
 	firstElement = (HASHELEMENT *) hashp->alloc(nelem * elementSize);
@@ -1567,15 +1562,15 @@ element_alloc(HTAB *hashp, int nelem)
 	}
 
 	/* if partitioned, must lock to touch freeList */
-	if (IS_PARTITIONED(hctlv))
-		SpinLockAcquire(&hctlv->mutex);
+	if (IS_PARTITIONED(hctl))
+		SpinLockAcquire(&hctl->mutex);
 
 	/* freelist could be nonempty if two backends did this concurrently */
-	firstElement->link = hctlv->freeList;
-	hctlv->freeList = prevElement;
+	firstElement->link = hctl->freeList;
+	hctl->freeList = prevElement;
 
-	if (IS_PARTITIONED(hctlv))
-		SpinLockRelease(&hctlv->mutex);
+	if (IS_PARTITIONED(hctl))
+		SpinLockRelease(&hctl->mutex);
 
 	return true;
 }
strip-volatile-ipc.patchapplication/octet-stream; name=strip-volatile-ipc.patchDownload
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index 250e312..78f15f0 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -170,29 +170,26 @@ ShmemAlloc(Size size)
 	Size		newFree;
 	void	   *newSpace;
 
-	/* use volatile pointer to prevent code rearrangement */
-	volatile PGShmemHeader *shmemseghdr = ShmemSegHdr;
-
 	/*
 	 * ensure all space is adequately aligned.
 	 */
 	size = MAXALIGN(size);
 
-	Assert(shmemseghdr != NULL);
+	Assert(ShmemSegHdr != NULL);
 
 	SpinLockAcquire(ShmemLock);
 
-	newStart = shmemseghdr->freeoffset;
+	newStart = ShmemSegHdr->freeoffset;
 
 	/* extra alignment for large requests, since they are probably buffers */
 	if (size >= BLCKSZ)
 		newStart = BUFFERALIGN(newStart);
 
 	newFree = newStart + size;
-	if (newFree <= shmemseghdr->totalsize)
+	if (newFree <= ShmemSegHdr->totalsize)
 	{
 		newSpace = (void *) ((char *) ShmemBase + newStart);
-		shmemseghdr->freeoffset = newFree;
+		ShmemSegHdr->freeoffset = newFree;
 	}
 	else
 		newSpace = NULL;
diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c
index a2fde89..3cc15e0 100644
--- a/src/backend/storage/ipc/sinvaladt.c
+++ b/src/backend/storage/ipc/sinvaladt.c
@@ -485,14 +485,9 @@ SIInsertDataEntries(const SharedInvalidationMessage *data, int n)
 		}
 
 		/* Update current value of maxMsgNum using spinlock */
-		{
-			/* use volatile pointer to prevent code rearrangement */
-			volatile SISeg *vsegP = segP;
-
-			SpinLockAcquire(&vsegP->msgnumLock);
-			vsegP->maxMsgNum = max;
-			SpinLockRelease(&vsegP->msgnumLock);
-		}
+		SpinLockAcquire(&segP->msgnumLock);
+		segP->maxMsgNum = max;
+		SpinLockRelease(&segP->msgnumLock);
 
 		/*
 		 * Now that the maxMsgNum change is globally visible, we give everyone
@@ -579,14 +574,9 @@ SIGetDataEntries(SharedInvalidationMessage *data, int datasize)
 	stateP->hasMessages = false;
 
 	/* Fetch current value of maxMsgNum using spinlock */
-	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile SISeg *vsegP = segP;
-
-		SpinLockAcquire(&vsegP->msgnumLock);
-		max = vsegP->maxMsgNum;
-		SpinLockRelease(&vsegP->msgnumLock);
-	}
+	SpinLockAcquire(&segP->msgnumLock);
+	max = segP->maxMsgNum;
+	SpinLockRelease(&segP->msgnumLock);
 
 	if (stateP->resetState)
 	{
#8Michael Paquier
michael.paquier@gmail.com
In reply to: Thomas Munro (#7)
1 attachment(s)
Re: Obsolete use of volatile in walsender.c, walreceiver.c, walreceiverfuncs.c?

On Fri, Oct 16, 2015 at 9:07 AM, Thomas Munro
<thomas.munro@enterprisedb.com> wrote:

On Wed, Oct 7, 2015 at 8:52 AM, Robert Haas <robertmhaas@gmail.com> wrote:

On Thu, Oct 1, 2015 at 11:01 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:

Right, see attached.

It seems to me that we could as well simplify checkpoint.c and
logical.c. In those files volatile casts are used as well to protect
from reordering for spinlock operations. See for example 0002 on top
of 0001 that is Thomas' patch.

These patches look good to me, so I have committed them.

Thanks. Also, spin.h's comment contains an out of date warning about
this. Here's a suggested fix for that, and a couple more volatrivia
patches.

I have looked at the rest of the code, and it seems that we can get
rid of volatile in a couple of extra places like in the attached as
those are used with spin locks. This applies on top of Thomas' set.
--
Michael

Attachments:

20151016_volatile_remove.patchtext/x-diff; charset=US-ASCII; name=20151016_volatile_remove.patchDownload
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index b13fe03..0dc4117 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -3718,8 +3718,6 @@ static int
 KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin,
 							   TransactionId xmax)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile ProcArrayStruct *pArray = procArray;
 	int			count = 0;
 	int			head,
 				tail;
@@ -3734,10 +3732,10 @@ KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin,
 	 *
 	 * Must take spinlock to ensure we see up-to-date array contents.
 	 */
-	SpinLockAcquire(&pArray->known_assigned_xids_lck);
-	tail = pArray->tailKnownAssignedXids;
-	head = pArray->headKnownAssignedXids;
-	SpinLockRelease(&pArray->known_assigned_xids_lck);
+	SpinLockAcquire(&procArray->known_assigned_xids_lck);
+	tail = procArray->tailKnownAssignedXids;
+	head = procArray->headKnownAssignedXids;
+	SpinLockRelease(&procArray->known_assigned_xids_lck);
 
 	for (i = tail; i < head; i++)
 	{
@@ -3777,8 +3775,6 @@ KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin,
 static TransactionId
 KnownAssignedXidsGetOldestXmin(void)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile ProcArrayStruct *pArray = procArray;
 	int			head,
 				tail;
 	int			i;
@@ -3786,10 +3782,10 @@ KnownAssignedXidsGetOldestXmin(void)
 	/*
 	 * Fetch head just once, since it may change while we loop.
 	 */
-	SpinLockAcquire(&pArray->known_assigned_xids_lck);
-	tail = pArray->tailKnownAssignedXids;
-	head = pArray->headKnownAssignedXids;
-	SpinLockRelease(&pArray->known_assigned_xids_lck);
+	SpinLockAcquire(&procArray->known_assigned_xids_lck);
+	tail = procArray->tailKnownAssignedXids;
+	head = procArray->headKnownAssignedXids;
+	SpinLockRelease(&procArray->known_assigned_xids_lck);
 
 	for (i = tail; i < head; i++)
 	{
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 2c2535b..bb10c1b 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -283,15 +283,13 @@ InitProcGlobal(void)
 void
 InitProcess(void)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile PROC_HDR *procglobal = ProcGlobal;
 	PGPROC * volatile * procgloballist;
 
 	/*
 	 * ProcGlobal should be set up already (if we are a backend, we inherit
 	 * this by fork() or EXEC_BACKEND mechanism from the postmaster).
 	 */
-	if (procglobal == NULL)
+	if (ProcGlobal == NULL)
 		elog(PANIC, "proc header uninitialized");
 
 	if (MyProc != NULL)
@@ -299,11 +297,11 @@ InitProcess(void)
 
 	/* Decide which list should supply our PGPROC. */
 	if (IsAnyAutoVacuumProcess())
-		procgloballist = &procglobal->autovacFreeProcs;
+		procgloballist = &ProcGlobal->autovacFreeProcs;
 	else if (IsBackgroundWorker)
-		procgloballist = &procglobal->bgworkerFreeProcs;
+		procgloballist = &ProcGlobal->bgworkerFreeProcs;
 	else
-		procgloballist = &procglobal->freeProcs;
+		procgloballist = &ProcGlobal->freeProcs;
 
 	/*
 	 * Try to get a proc struct from the appropriate free list.  If this
@@ -314,7 +312,7 @@ InitProcess(void)
 	 */
 	SpinLockAcquire(ProcStructLock);
 
-	set_spins_per_delay(procglobal->spins_per_delay);
+	set_spins_per_delay(ProcGlobal->spins_per_delay);
 
 	MyProc = *procgloballist;
 
@@ -578,13 +576,10 @@ InitAuxiliaryProcess(void)
 void
 PublishStartupProcessInformation(void)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile PROC_HDR *procglobal = ProcGlobal;
-
 	SpinLockAcquire(ProcStructLock);
 
-	procglobal->startupProc = MyProc;
-	procglobal->startupProcPid = MyProcPid;
+	ProcGlobal->startupProc = MyProc;
+	ProcGlobal->startupProcPid = MyProcPid;
 
 	SpinLockRelease(ProcStructLock);
 }
@@ -627,12 +622,9 @@ HaveNFreeProcs(int n)
 {
 	PGPROC	   *proc;
 
-	/* use volatile pointer to prevent code rearrangement */
-	volatile PROC_HDR *procglobal = ProcGlobal;
-
 	SpinLockAcquire(ProcStructLock);
 
-	proc = procglobal->freeProcs;
+	proc = ProcGlobal->freeProcs;
 
 	while (n > 0 && proc != NULL)
 	{
@@ -772,8 +764,6 @@ RemoveProcFromArray(int code, Datum arg)
 static void
 ProcKill(int code, Datum arg)
 {
-	/* use volatile pointer to prevent code rearrangement */
-	volatile PROC_HDR *procglobal = ProcGlobal;
 	PGPROC	   *proc;
 	PGPROC * volatile * procgloballist;
 
@@ -822,7 +812,7 @@ ProcKill(int code, Datum arg)
 	*procgloballist = proc;
 
 	/* Update shared estimate of spins_per_delay */
-	procglobal->spins_per_delay = update_spins_per_delay(procglobal->spins_per_delay);
+	ProcGlobal->spins_per_delay = update_spins_per_delay(ProcGlobal->spins_per_delay);
 
 	SpinLockRelease(ProcStructLock);
 
@@ -1644,9 +1634,6 @@ ProcSendSignal(int pid)
 
 	if (RecoveryInProgress())
 	{
-		/* use volatile pointer to prevent code rearrangement */
-		volatile PROC_HDR *procglobal = ProcGlobal;
-
 		SpinLockAcquire(ProcStructLock);
 
 		/*
@@ -1657,8 +1644,8 @@ ProcSendSignal(int pid)
 		 * backend, so BackendPidGetProc() will not return any pid at all. So
 		 * we remember the information for this special case.
 		 */
-		if (pid == procglobal->startupProcPid)
-			proc = procglobal->startupProc;
+		if (pid == ProcGlobal->startupProcPid)
+			proc = ProcGlobal->startupProc;
 
 		SpinLockRelease(ProcStructLock);
 	}
#9Robert Haas
robertmhaas@gmail.com
In reply to: Michael Paquier (#8)
Re: Obsolete use of volatile in walsender.c, walreceiver.c, walreceiverfuncs.c?

On Thu, Oct 15, 2015 at 10:36 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:

On Fri, Oct 16, 2015 at 9:07 AM, Thomas Munro
<thomas.munro@enterprisedb.com> wrote:

On Wed, Oct 7, 2015 at 8:52 AM, Robert Haas <robertmhaas@gmail.com> wrote:

On Thu, Oct 1, 2015 at 11:01 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:

Right, see attached.

It seems to me that we could as well simplify checkpoint.c and
logical.c. In those files volatile casts are used as well to protect
from reordering for spinlock operations. See for example 0002 on top
of 0001 that is Thomas' patch.

These patches look good to me, so I have committed them.

Thanks. Also, spin.h's comment contains an out of date warning about
this. Here's a suggested fix for that, and a couple more volatrivia
patches.

I have looked at the rest of the code, and it seems that we can get
rid of volatile in a couple of extra places like in the attached as
those are used with spin locks. This applies on top of Thomas' set.

OK, committed his, and yours.

I back-patched his spin.h comment fix to 9.5 since that's a factual
error, but the rest of this seems like optimization so I committed it
only to master.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#10Michael Paquier
michael.paquier@gmail.com
In reply to: Robert Haas (#9)
Re: Obsolete use of volatile in walsender.c, walreceiver.c, walreceiverfuncs.c?

On Sat, Oct 17, 2015 at 3:21 AM, Robert Haas wrote:

OK, committed his, and yours.

I back-patched his spin.h comment fix to 9.5 since that's a factual
error, but the rest of this seems like optimization so I committed it
only to master.

That sounds right. Thanks!
--
Michael

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers