diff options
Diffstat (limited to 'src/backend/storage/lmgr/proc.c')
-rw-r--r-- | src/backend/storage/lmgr/proc.c | 67 |
1 files changed, 53 insertions, 14 deletions
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index de09b4a5b05..ae8fb17fcab 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.48 1999/02/13 23:18:28 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.49 1999/02/19 06:06:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -46,7 +46,7 @@ * This is so that we can support more backends. (system-wide semaphore * sets run out pretty fast.) -ay 4/95 * - * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.48 1999/02/13 23:18:28 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.49 1999/02/19 06:06:08 tgl Exp $ */ #include <sys/time.h> #include <unistd.h> @@ -108,13 +108,24 @@ static void ProcFreeSem(IpcSemaphoreKey semKey, int semNum); /* * InitProcGlobal - * initializes the global process table. We put it here so that - * the postmaster can do this initialization. (ProcFreeAllSem needs + * the postmaster can do this initialization. (ProcFreeAllSemaphores needs * to read this table on exiting the postmaster. If we have the first * backend do this, starting up and killing the postmaster without * starting any backends will be a problem.) + * + * We also allocate all the per-process semaphores we will need to support + * the requested number of backends. We used to allocate semaphores + * only when backends were actually started up, but that is bad because + * it lets Postgres fail under load --- a lot of Unix systems are + * (mis)configured with small limits on the number of semaphores, and + * running out when trying to start another backend is a common failure. + * So, now we grab enough semaphores to support the desired max number + * of backends immediately at initialization --- if the sysadmin has set + * MaxBackends higher than his kernel will support, he'll find out sooner + * rather than later. */ void -InitProcGlobal(IPCKey key) +InitProcGlobal(IPCKey key, int maxBackends) { bool found = false; @@ -134,6 +145,24 @@ InitProcGlobal(IPCKey key) ProcGlobal->currKey = IPCGetProcessSemaphoreInitKey(key); for (i = 0; i < MAX_PROC_SEMS / PROC_NSEMS_PER_SET; i++) ProcGlobal->freeSemMap[i] = 0; + /* Pre-create the semaphores for the first maxBackends processes */ + for (i = 0; + i < (maxBackends+PROC_NSEMS_PER_SET-1) / PROC_NSEMS_PER_SET; + i++) + { + IPCKey semKey = ProcGlobal->currKey + i; + int semId; + int semstat; + + semId = IpcSemaphoreCreate(semKey, + PROC_NSEMS_PER_SET, + IPCProtection, + IpcSemaphoreDefaultStartValue, + 0, + &semstat); + /* mark this sema set allocated */ + ProcGlobal->freeSemMap[i] = (1 << PROC_NSEMS_PER_SET); + } } } @@ -222,6 +251,11 @@ InitProcess(IPCKey key) ProcGetNewSemKeyAndNum(&semKey, &semNum); + /* Note: because of the pre-allocation done in InitProcGlobal, + * this call should always attach to an existing semaphore. + * It will (try to) create a new group of semaphores only if + * the postmaster tries to start more backends than it said it would. + */ semId = IpcSemaphoreCreate(semKey, PROC_NSEMS_PER_SET, IPCProtection, @@ -823,20 +857,20 @@ ProcGetNewSemKeyAndNum(IPCKey *key, int *semNum) { int i; int32 *freeSemMap = ProcGlobal->freeSemMap; - unsigned int fullmask; + int32 fullmask = (1 << (PROC_NSEMS_PER_SET+1)) - 1; /* * we hold ProcStructLock when entering this routine. We scan through * the bitmap to look for a free semaphore. */ - fullmask = ~0 >> (32 - PROC_NSEMS_PER_SET); + for (i = 0; i < MAX_PROC_SEMS / PROC_NSEMS_PER_SET; i++) { int mask = 1; int j; if (freeSemMap[i] == fullmask) - continue; /* none free for this set */ + continue; /* this set is fully allocated */ for (j = 0; j < PROC_NSEMS_PER_SET; j++) { @@ -845,8 +879,9 @@ ProcGetNewSemKeyAndNum(IPCKey *key, int *semNum) /* * a free semaphore found. Mark it as allocated. + * Also set the bit indicating whole set is allocated. */ - freeSemMap[i] |= mask; + freeSemMap[i] |= mask + (1 << PROC_NSEMS_PER_SET); *key = ProcGlobal->currKey + i; *semNum = j; @@ -862,8 +897,7 @@ ProcGetNewSemKeyAndNum(IPCKey *key, int *semNum) /* * ProcFreeSem - - * free up our semaphore in the semaphore set. If we're the last one - * in the set, also remove the semaphore set. + * free up our semaphore in the semaphore set. */ static void ProcFreeSem(IpcSemaphoreKey semKey, int semNum) @@ -876,14 +910,19 @@ ProcFreeSem(IpcSemaphoreKey semKey, int semNum) mask = ~(1 << semNum); freeSemMap[i] &= mask; - if (freeSemMap[i] == 0) - IpcSemaphoreKill(semKey); + /* Formerly we'd release a semaphore set if it was now completely unused, + * but now we keep the semaphores to ensure we won't run out when + * starting new backends --- cf. InitProcGlobal. Note that the + * PROC_NSEMS_PER_SET+1'st bit of the freeSemMap entry remains set to + * indicate it is still allocated; ProcFreeAllSemaphores() needs that. + */ } /* * ProcFreeAllSemaphores - - * on exiting the postmaster, we free up all the semaphores allocated - * to the lmgrs of the backends. + * called at shmem_exit time, ie when exiting the postmaster or + * destroying shared state for a failed set of backends. + * Free up all the semaphores allocated to the lmgrs of the backends. */ void ProcFreeAllSemaphores() |