]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Move ProcStructLock to the ProcGlobal struct
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Wed, 11 Feb 2026 14:48:45 +0000 (16:48 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Wed, 11 Feb 2026 14:48:45 +0000 (16:48 +0200)
It protects the freeProcs and some other fields in ProcGlobal, so
let's move it there. It's good for cache locality to have it next to
the thing it protects, and just makes more sense anyway. I believe it
was allocated as a separate shared memory area just for historical
reasons.

Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Discussion: https://www.postgresql.org/message-id/b78719db-0c54-409f-b185-b0d59261143f@iki.fi

src/backend/postmaster/launch_backend.c
src/backend/storage/lmgr/proc.c
src/include/storage/proc.h

index 05b1feef3cf1d746bae96495c53641fd4ed74163..e9134b9751b41da638571d91cb5d960622cf60af 100644 (file)
@@ -104,7 +104,6 @@ typedef struct
        char      **LWLockTrancheNames;
        int                *LWLockCounter;
        LWLockPadded *MainLWLockArray;
-       slock_t    *ProcStructLock;
        PROC_HDR   *ProcGlobal;
        PGPROC     *AuxiliaryProcs;
        PGPROC     *PreparedXactProcs;
@@ -735,7 +734,6 @@ save_backend_variables(BackendParameters *param,
        param->LWLockTrancheNames = LWLockTrancheNames;
        param->LWLockCounter = LWLockCounter;
        param->MainLWLockArray = MainLWLockArray;
-       param->ProcStructLock = ProcStructLock;
        param->ProcGlobal = ProcGlobal;
        param->AuxiliaryProcs = AuxiliaryProcs;
        param->PreparedXactProcs = PreparedXactProcs;
@@ -995,7 +993,6 @@ restore_backend_variables(BackendParameters *param)
        LWLockTrancheNames = param->LWLockTrancheNames;
        LWLockCounter = param->LWLockCounter;
        MainLWLockArray = param->MainLWLockArray;
-       ProcStructLock = param->ProcStructLock;
        ProcGlobal = param->ProcGlobal;
        AuxiliaryProcs = param->AuxiliaryProcs;
        PreparedXactProcs = param->PreparedXactProcs;
index 31ccdb1ef89bfc02b60dff1f1e5246a1f6c4307a..fd8318bdf3d63efa7a22ccbbd5b9189ec92dce78 100644 (file)
@@ -66,15 +66,6 @@ bool         log_lock_waits = true;
 /* Pointer to this process's PGPROC struct, if any */
 PGPROC    *MyProc = NULL;
 
-/*
- * This spinlock protects the freelist of recycled PGPROC structures.
- * We cannot use an LWLock because the LWLock manager depends on already
- * having a PGPROC and a wait semaphore!  But these structures are touched
- * relatively infrequently (only at backend startup or shutdown) and not for
- * very long, so a spinlock is okay.
- */
-NON_EXEC_STATIC slock_t *ProcStructLock = NULL;
-
 /* Pointers to shared-memory structures */
 PROC_HDR   *ProcGlobal = NULL;
 NON_EXEC_STATIC PGPROC *AuxiliaryProcs = NULL;
@@ -214,6 +205,7 @@ InitProcGlobal(void)
         * Initialize the data structures.
         */
        ProcGlobal->spins_per_delay = DEFAULT_SPINS_PER_DELAY;
+       SpinLockInit(&ProcGlobal->freeProcsLock);
        dlist_init(&ProcGlobal->freeProcs);
        dlist_init(&ProcGlobal->autovacFreeProcs);
        dlist_init(&ProcGlobal->bgworkerFreeProcs);
@@ -378,12 +370,6 @@ InitProcGlobal(void)
         */
        AuxiliaryProcs = &procs[MaxBackends];
        PreparedXactProcs = &procs[MaxBackends + NUM_AUXILIARY_PROCS];
-
-       /* Create ProcStructLock spinlock, too */
-       ProcStructLock = (slock_t *) ShmemInitStruct("ProcStructLock spinlock",
-                                                                                                sizeof(slock_t),
-                                                                                                &found);
-       SpinLockInit(ProcStructLock);
 }
 
 /*
@@ -429,17 +415,17 @@ InitProcess(void)
         * Try to get a proc struct from the appropriate free list.  If this
         * fails, we must be out of PGPROC structures (not to mention semaphores).
         *
-        * While we are holding the ProcStructLock, also copy the current shared
+        * While we are holding the spinlock, also copy the current shared
         * estimate of spins_per_delay to local storage.
         */
-       SpinLockAcquire(ProcStructLock);
+       SpinLockAcquire(&ProcGlobal->freeProcsLock);
 
        set_spins_per_delay(ProcGlobal->spins_per_delay);
 
        if (!dlist_is_empty(procgloballist))
        {
                MyProc = dlist_container(PGPROC, links, dlist_pop_head_node(procgloballist));
-               SpinLockRelease(ProcStructLock);
+               SpinLockRelease(&ProcGlobal->freeProcsLock);
        }
        else
        {
@@ -449,7 +435,7 @@ InitProcess(void)
                 * error message.  XXX do we need to give a different failure message
                 * in the autovacuum case?
                 */
-               SpinLockRelease(ProcStructLock);
+               SpinLockRelease(&ProcGlobal->freeProcsLock);
                if (AmWalSenderProcess())
                        ereport(FATAL,
                                        (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
@@ -634,13 +620,13 @@ InitAuxiliaryProcess(void)
                RegisterPostmasterChildActive();
 
        /*
-        * We use the ProcStructLock to protect assignment and releasing of
+        * We use the freeProcsLock to protect assignment and releasing of
         * AuxiliaryProcs entries.
         *
-        * While we are holding the ProcStructLock, also copy the current shared
+        * While we are holding the spinlock, also copy the current shared
         * estimate of spins_per_delay to local storage.
         */
-       SpinLockAcquire(ProcStructLock);
+       SpinLockAcquire(&ProcGlobal->freeProcsLock);
 
        set_spins_per_delay(ProcGlobal->spins_per_delay);
 
@@ -655,7 +641,7 @@ InitAuxiliaryProcess(void)
        }
        if (proctype >= NUM_AUXILIARY_PROCS)
        {
-               SpinLockRelease(ProcStructLock);
+               SpinLockRelease(&ProcGlobal->freeProcsLock);
                elog(FATAL, "all AuxiliaryProcs are in use");
        }
 
@@ -663,7 +649,7 @@ InitAuxiliaryProcess(void)
        /* use volatile pointer to prevent code rearrangement */
        ((volatile PGPROC *) auxproc)->pid = MyProcPid;
 
-       SpinLockRelease(ProcStructLock);
+       SpinLockRelease(&ProcGlobal->freeProcsLock);
 
        MyProc = auxproc;
        MyProcNumber = GetNumberFromPGProc(MyProc);
@@ -789,7 +775,7 @@ HaveNFreeProcs(int n, int *nfree)
        Assert(n > 0);
        Assert(nfree);
 
-       SpinLockAcquire(ProcStructLock);
+       SpinLockAcquire(&ProcGlobal->freeProcsLock);
 
        *nfree = 0;
        dlist_foreach(iter, &ProcGlobal->freeProcs)
@@ -799,7 +785,7 @@ HaveNFreeProcs(int n, int *nfree)
                        break;
        }
 
-       SpinLockRelease(ProcStructLock);
+       SpinLockRelease(&ProcGlobal->freeProcsLock);
 
        return (*nfree == n);
 }
@@ -980,9 +966,9 @@ ProcKill(int code, Datum arg)
                                procgloballist = leader->procgloballist;
 
                                /* Leader exited first; return its PGPROC. */
-                               SpinLockAcquire(ProcStructLock);
+                               SpinLockAcquire(&ProcGlobal->freeProcsLock);
                                dlist_push_head(procgloballist, &leader->links);
-                               SpinLockRelease(ProcStructLock);
+                               SpinLockRelease(&ProcGlobal->freeProcsLock);
                        }
                }
                else if (leader != MyProc)
@@ -1013,7 +999,7 @@ ProcKill(int code, Datum arg)
        proc->vxid.lxid = InvalidTransactionId;
 
        procgloballist = proc->procgloballist;
-       SpinLockAcquire(ProcStructLock);
+       SpinLockAcquire(&ProcGlobal->freeProcsLock);
 
        /*
         * If we're still a member of a locking group, that means we're a leader
@@ -1032,7 +1018,7 @@ ProcKill(int code, Datum arg)
        /* Update shared estimate of spins_per_delay */
        ProcGlobal->spins_per_delay = update_spins_per_delay(ProcGlobal->spins_per_delay);
 
-       SpinLockRelease(ProcStructLock);
+       SpinLockRelease(&ProcGlobal->freeProcsLock);
 }
 
 /*
@@ -1072,7 +1058,7 @@ AuxiliaryProcKill(int code, Datum arg)
        MyProcNumber = INVALID_PROC_NUMBER;
        DisownLatch(&proc->procLatch);
 
-       SpinLockAcquire(ProcStructLock);
+       SpinLockAcquire(&ProcGlobal->freeProcsLock);
 
        /* Mark auxiliary proc no longer in use */
        proc->pid = 0;
@@ -1082,7 +1068,7 @@ AuxiliaryProcKill(int code, Datum arg)
        /* Update shared estimate of spins_per_delay */
        ProcGlobal->spins_per_delay = update_spins_per_delay(ProcGlobal->spins_per_delay);
 
-       SpinLockRelease(ProcStructLock);
+       SpinLockRelease(&ProcGlobal->freeProcsLock);
 }
 
 /*
index ac0df4aeaaab50d112957b4016f2ac94c24b64fa..23e5cd98161c0bd7f4fb11aa2a2ffd9398412725 100644 (file)
@@ -420,6 +420,16 @@ typedef struct PROC_HDR
 
        /* Length of allProcs array */
        uint32          allProcCount;
+
+       /*
+        * This spinlock protects the below freelists of PGPROC structures.  We
+        * cannot use an LWLock because the LWLock manager depends on already
+        * having a PGPROC and a wait semaphore!  But these structures are touched
+        * relatively infrequently (only at backend startup or shutdown) and not
+        * for very long, so a spinlock is okay.
+        */
+       slock_t         freeProcsLock;
+
        /* Head of list of free PGPROC structures */
        dlist_head      freeProcs;
        /* Head of list of autovacuum & special worker free PGPROC structures */
@@ -428,6 +438,7 @@ typedef struct PROC_HDR
        dlist_head      bgworkerFreeProcs;
        /* Head of list of walsender free PGPROC structures */
        dlist_head      walsenderFreeProcs;
+
        /* First pgproc waiting for group XID clear */
        pg_atomic_uint32 procArrayGroupFirst;
        /* First pgproc waiting for group transaction status update */
@@ -489,7 +500,6 @@ extern PGDLLIMPORT int IdleSessionTimeout;
 extern PGDLLIMPORT bool log_lock_waits;
 
 #ifdef EXEC_BACKEND
-extern PGDLLIMPORT slock_t *ProcStructLock;
 extern PGDLLIMPORT PGPROC *AuxiliaryProcs;
 #endif