diff --git a/src/backend/postmaster/launch_backend.c b/src/backend/postmaster/launch_backend.c index 05b1feef3cf..e9134b9751b 100644 --- a/src/backend/postmaster/launch_backend.c +++ b/src/backend/postmaster/launch_backend.c @@ -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; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 31ccdb1ef89..fd8318bdf3d 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -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); } /* diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h index ac0df4aeaaa..23e5cd98161 100644 --- a/src/include/storage/proc.h +++ b/src/include/storage/proc.h @@ -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