diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index ee033160508..c7b1e45bb81 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -160,75 +160,68 @@ InitProcGlobal(void) PGPROC *procs; int i; bool found; + uint32 TotalProcs = MaxBackends + NUM_AUXILIARY_PROCS; /* Create the ProcGlobal shared structure */ ProcGlobal = (PROC_HDR *) ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &found); Assert(!found); - /* - * Create the PGPROC structures for auxiliary (bgwriter) processes, too. - * These do not get linked into the freeProcs list. - */ - AuxiliaryProcs = (PGPROC *) - ShmemInitStruct("AuxiliaryProcs", NUM_AUXILIARY_PROCS * sizeof(PGPROC), - &found); - Assert(!found); - /* * Initialize the data structures. */ + ProcGlobal->spins_per_delay = DEFAULT_SPINS_PER_DELAY; ProcGlobal->freeProcs = NULL; ProcGlobal->autovacFreeProcs = NULL; - ProcGlobal->spins_per_delay = DEFAULT_SPINS_PER_DELAY; - /* - * Pre-create the PGPROC structures and create a semaphore for each. - */ - procs = (PGPROC *) ShmemAlloc((MaxConnections) * sizeof(PGPROC)); - if (!procs) - ereport(FATAL, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of shared memory"))); - MemSet(procs, 0, MaxConnections * sizeof(PGPROC)); - for (i = 0; i < MaxConnections; i++) - { - PGSemaphoreCreate(&(procs[i].sem)); - procs[i].links.next = (SHM_QUEUE *) ProcGlobal->freeProcs; - ProcGlobal->freeProcs = &procs[i]; - InitSharedLatch(&procs[i].waitLatch); - } - - /* - * Likewise for the PGPROCs reserved for autovacuum. + * Create and initialize all the PGPROC structures we'll need (except for + * those used for 2PC, which are embedded within a GlobalTransactionData + * struct). * - * Note: the "+1" here accounts for the autovac launcher + * There are three separate consumers of PGPROC structures: (1) normal + * backends, (2) autovacuum workers and the autovacuum launcher, and (3) + * auxiliary processes. Each PGPROC structure is dedicated to exactly + * one of these purposes, and they do not move between groups. */ - procs = (PGPROC *) ShmemAlloc((autovacuum_max_workers + 1) * sizeof(PGPROC)); + procs = (PGPROC *) ShmemAlloc(TotalProcs * sizeof(PGPROC)); if (!procs) ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); - MemSet(procs, 0, (autovacuum_max_workers + 1) * sizeof(PGPROC)); - for (i = 0; i < autovacuum_max_workers + 1; i++) + MemSet(procs, 0, TotalProcs * sizeof(PGPROC)); + for (i = 0; i < TotalProcs; i++) { + /* Common initialization for all PGPROCs, regardless of type. */ PGSemaphoreCreate(&(procs[i].sem)); - procs[i].links.next = (SHM_QUEUE *) ProcGlobal->autovacFreeProcs; - ProcGlobal->autovacFreeProcs = &procs[i]; InitSharedLatch(&procs[i].waitLatch); + + /* + * Newly created PGPROCs for normal backends or for autovacuum must + * be queued up on the appropriate free list. Because there can only + * ever be a small, fixed number of auxiliary processes, no free + * list is used in that case; InitAuxiliaryProcess() instead uses a + * linear search. + */ + if (i < MaxConnections) + { + /* PGPROC for normal backend, add to freeProcs list */ + procs[i].links.next = (SHM_QUEUE *) ProcGlobal->freeProcs; + ProcGlobal->freeProcs = &procs[i]; + } + else if (i < MaxBackends) + { + /* PGPROC for AV launcher/worker, add to autovacFreeProcs list */ + procs[i].links.next = (SHM_QUEUE *) ProcGlobal->autovacFreeProcs; + ProcGlobal->autovacFreeProcs = &procs[i]; + } } /* - * And auxiliary procs. + * Save a pointer to the block of PGPROC structures reserved for + * auxiliary proceses. */ - MemSet(AuxiliaryProcs, 0, NUM_AUXILIARY_PROCS * sizeof(PGPROC)); - for (i = 0; i < NUM_AUXILIARY_PROCS; i++) - { - AuxiliaryProcs[i].pid = 0; /* marks auxiliary proc as not in use */ - PGSemaphoreCreate(&(AuxiliaryProcs[i].sem)); - InitSharedLatch(&procs[i].waitLatch); - } + AuxiliaryProcs = &procs[MaxBackends]; /* Create ProcStructLock spinlock, too */ ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t));