From 455db18cb525d151f0dee40738023efbcdecdae4 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Tue, 10 Feb 2026 22:47:22 +0200
Subject: [PATCH v2 4/4] Rearrange fields in PGPROC, for clarity

---
 src/include/storage/proc.h | 124 +++++++++++++++++++++----------------
 1 file changed, 71 insertions(+), 53 deletions(-)

diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index f642830fcf8..b1077562cb5 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -184,27 +184,31 @@ typedef struct PGPROC
 	dlist_node	freeProcsLink;	/* link in procgloballist, when in recycled
 								 * state */
 
-	PGSemaphore sem;			/* ONE semaphore to sleep on */
-	ProcWaitStatus waitStatus;
-
-	Latch		procLatch;		/* generic latch for process */
+	/*---- Backend identity ----*/
 
+	/*
+	 * These fields that don't change after backend startup, or only very
+	 * rarely
+	 */
+	int			pid;			/* Backend's process ID; 0 if prepared xact */
+	BackendType backendType;	/* what kind of process is this? */
 
-	TransactionId xid;			/* id of top-level transaction currently being
-								 * executed by this proc, if running and XID
-								 * is assigned; else InvalidTransactionId.
-								 * mirrored in ProcGlobal->xids[pgxactoff] */
-
-	TransactionId xmin;			/* minimal running XID as it was when we were
-								 * starting our xact, excluding LAZY VACUUM:
-								 * vacuum must not remove tuples deleted by
-								 * xid >= xmin ! */
+	/* These fields are zero while a backend is still starting up: */
+	Oid			databaseId;		/* OID of database this backend is using */
+	Oid			roleId;			/* OID of role using this backend */
 
-	int			pid;			/* Backend's process ID; 0 if prepared xact */
+	Oid			tempNamespaceId;	/* OID of temp schema this backend is
+									 * using */
 
 	int			pgxactoff;		/* offset into various ProcGlobal->arrays with
 								 * data mirrored from this PGPROC */
 
+	uint8		statusFlags;	/* this backend's status flags, see PROC_*
+								 * above. mirrored in
+								 * ProcGlobal->statusFlags[pgxactoff] */
+
+	/*---- Transactions and snapshots ----*/
+
 	/*
 	 * Currently running top-level transaction's virtual xid. Together these
 	 * form a VirtualTransactionId, but we don't use that struct because this
@@ -224,14 +228,27 @@ typedef struct PGPROC
 									 * InvalidLocalTransactionId */
 	}			vxid;
 
-	/* These fields are zero while a backend is still starting up: */
-	Oid			databaseId;		/* OID of database this backend is using */
-	Oid			roleId;			/* OID of role using this backend */
+	TransactionId xid;			/* id of top-level transaction currently being
+								 * executed by this proc, if running and XID
+								 * is assigned; else InvalidTransactionId.
+								 * mirrored in ProcGlobal->xids[pgxactoff] */
 
-	Oid			tempNamespaceId;	/* OID of temp schema this backend is
-									 * using */
+	TransactionId xmin;			/* minimal running XID as it was when we were
+								 * starting our xact, excluding LAZY VACUUM:
+								 * vacuum must not remove tuples deleted by
+								 * xid >= xmin ! */
 
-	BackendType backendType;	/* what kind of process is this? */
+	XidCacheStatus subxidStatus;	/* mirrored with
+									 * ProcGlobal->subxidStates[i] */
+	struct XidCache subxids;	/* cache for subtransaction XIDs */
+
+	/*---- Inter-process signaling ----*/
+
+	Latch		procLatch;		/* generic latch for process */
+
+	PGSemaphore sem;			/* ONE semaphore to sleep on */
+
+	int			delayChkptFlags;	/* for DELAY_CHKPT_* flags */
 
 	/*
 	 * While in hot standby mode, shows that a conflict signal has been sent
@@ -243,6 +260,8 @@ typedef struct PGPROC
 	 */
 	pg_atomic_uint32 pendingRecoveryConflicts;
 
+	/*---- LWLock waiting ----*/
+
 	/*
 	 * Info about LWLock the process is currently waiting for, if any.
 	 *
@@ -257,6 +276,16 @@ typedef struct PGPROC
 	/* Support for condition variables. */
 	proclist_node cvWaitLink;	/* position in CV wait list */
 
+	/*---- Lock manager data ----*/
+
+	/*
+	 * Support for lock groups.  Use LockHashPartitionLockByProc on the group
+	 * leader to get the LWLock protecting these fields.
+	 */
+	PGPROC	   *lockGroupLeader;	/* lock group leader, if I'm a member */
+	dlist_head	lockGroupMembers;	/* list of members, if I'm a leader */
+	dlist_node	lockGroupLink;	/* my member link, if I'm a member */
+
 	/* Info about lock the process is currently waiting for, if any. */
 	/* waitLock and waitProcLock are NULL if not currently waiting. */
 	LOCK	   *waitLock;		/* Lock object we're sleeping on ... */
@@ -265,14 +294,28 @@ typedef struct PGPROC
 	LOCKMODE	waitLockMode;	/* type of lock we're waiting for */
 	LOCKMASK	heldLocks;		/* bitmask for lock types already held on this
 								 * lock object by this backend */
+
 	pg_atomic_uint64 waitStart; /* time at which wait for lock acquisition
 								 * started */
 
-	int			delayChkptFlags;	/* for DELAY_CHKPT_* flags */
+	ProcWaitStatus waitStatus;
 
-	uint8		statusFlags;	/* this backend's status flags, see PROC_*
-								 * above. mirrored in
-								 * ProcGlobal->statusFlags[pgxactoff] */
+	/*
+	 * All PROCLOCK objects for locks held or awaited by this backend are
+	 * linked into one of these lists, according to the partition number of
+	 * their lock.
+	 */
+	dlist_head	myProcLocks[NUM_LOCK_PARTITIONS];
+
+	/*-- recording fast-path locks taken by this backend. --*/
+	LWLock		fpInfoLock;		/* protects per-backend fast-path state */
+	uint64	   *fpLockBits;		/* lock modes held for each fast-path slot */
+	Oid		   *fpRelId;		/* slots for rel oids */
+	bool		fpVXIDLock;		/* are we holding a fast-path VXID lock? */
+	LocalTransactionId fpLocalTransactionId;	/* lxid for fast-path VXID
+												 * lock */
+
+	/*---- Synchronous replication waiting ----*/
 
 	/*
 	 * Info to allow us to wait for synchronous replication, if needed.
@@ -284,18 +327,8 @@ typedef struct PGPROC
 	int			syncRepState;	/* wait state for sync rep */
 	dlist_node	syncRepLinks;	/* list link if process is in syncrep queue */
 
-	/*
-	 * All PROCLOCK objects for locks held or awaited by this backend are
-	 * linked into one of these lists, according to the partition number of
-	 * their lock.
-	 */
-	dlist_head	myProcLocks[NUM_LOCK_PARTITIONS];
-
-	XidCacheStatus subxidStatus;	/* mirrored with
-									 * ProcGlobal->subxidStates[i] */
-	struct XidCache subxids;	/* cache for subtransaction XIDs */
+	/*---- Support for group XID clearing. ----*/
 
-	/* Support for group XID clearing. */
 	/* true, if member of ProcArray group waiting for XID clear */
 	bool		procArrayGroupMember;
 	/* next ProcArray group member waiting for XID clear */
@@ -307,9 +340,7 @@ typedef struct PGPROC
 	 */
 	TransactionId procArrayGroupMemberXid;
 
-	uint32		wait_event_info;	/* proc's wait information */
-
-	/* Support for group transaction status update. */
+	/*---- Support for group transaction status update. ----*/
 	bool		clogGroupMember;	/* true, if member of clog group */
 	pg_atomic_uint32 clogGroupNext; /* next clog group member */
 	TransactionId clogGroupMemberXid;	/* transaction id of clog group member */
@@ -320,21 +351,8 @@ typedef struct PGPROC
 	XLogRecPtr	clogGroupMemberLsn; /* WAL location of commit record for clog
 									 * group member */
 
-	/* Lock manager data, recording fast-path locks taken by this backend. */
-	LWLock		fpInfoLock;		/* protects per-backend fast-path state */
-	uint64	   *fpLockBits;		/* lock modes held for each fast-path slot */
-	Oid		   *fpRelId;		/* slots for rel oids */
-	bool		fpVXIDLock;		/* are we holding a fast-path VXID lock? */
-	LocalTransactionId fpLocalTransactionId;	/* lxid for fast-path VXID
-												 * lock */
-
-	/*
-	 * Support for lock groups.  Use LockHashPartitionLockByProc on the group
-	 * leader to get the LWLock protecting these fields.
-	 */
-	PGPROC	   *lockGroupLeader;	/* lock group leader, if I'm a member */
-	dlist_head	lockGroupMembers;	/* list of members, if I'm a leader */
-	dlist_node	lockGroupLink;	/* my member link, if I'm a member */
+	/*---- Status reporting ----*/
+	uint32		wait_event_info;	/* proc's wait information */
 }
 
 /*
-- 
2.47.3

