/* * InitShmemAllocation() --- set up shared-memory space allocation. * * This should be called only in the postmaster or a standalone backend. */ void InitShmemAllocation(void) { PGShmemHeader *shmhdr = ShmemSegHdr; char *aligned; Assert(shmhdr != NULL); /* * Initialize the spinlock used by ShmemAlloc. We must use * ShmemAllocUnlocked, since obviously ShmemAlloc can't be called yet. */ ShmemLock = (slock_t *) ShmemAllocUnlocked(sizeof(slock_t)); SpinLockInit(ShmemLock); /* * Allocations after this point should go through ShmemAlloc, which * expects to allocate everything on cache line boundaries. Make sure the * first allocation begins on a cache line boundary. */ aligned = (char *) (CACHELINEALIGN((((char *) shmhdr) + shmhdr->freeoffset))); shmhdr->freeoffset = aligned - (char *) shmhdr; /* ShmemIndex can't be set up yet (need LWLocks first) */ shmhdr->index = NULL; ShmemIndex = (HTAB *) NULL; /* * Initialize ShmemVariableCache for transaction manager. (This doesn't * really belong here, but not worth moving.) */ ShmemVariableCache = (VariableCache) ShmemAlloc(sizeof(*ShmemVariableCache)); memset(ShmemVariableCache, 0, sizeof(*ShmemVariableCache)); }
/* * PGReserveSemaphores --- initialize semaphore support * * This is called during postmaster start or shared memory reinitialization. * It should do whatever is needed to be able to support up to maxSemas * subsequent PGSemaphoreCreate calls. Also, if any system resources * are acquired here or in PGSemaphoreCreate, register an on_shmem_exit * callback to release them. * * The port number is passed for possible use as a key (for SysV, we use * it to generate the starting semaphore key). In a standalone backend, * zero will be passed. * * In the SysV implementation, we acquire semaphore sets on-demand; the * maxSemas parameter is just used to size the arrays. There is an array * of PGSemaphoreData structs in shared memory, and a postmaster-local array * with one entry per SysV semaphore set, which we use for releasing the * semaphore sets when done. (This design ensures that postmaster shutdown * doesn't rely on the contents of shared memory, which a failed backend might * have clobbered.) */ void PGReserveSemaphores(int maxSemas, int port) { /* * We must use ShmemAllocUnlocked(), since the spinlock protecting * ShmemAlloc() won't be ready yet. (This ordering is necessary when we * are emulating spinlocks with semaphores.) */ sharedSemas = (PGSemaphore) ShmemAllocUnlocked(PGSemaphoreShmemSize(maxSemas)); numSharedSemas = 0; maxSharedSemas = maxSemas; maxSemaSets = (maxSemas + SEMAS_PER_SET - 1) / SEMAS_PER_SET; mySemaSets = (IpcSemaphoreId *) malloc(maxSemaSets * sizeof(IpcSemaphoreId)); if (mySemaSets == NULL) elog(PANIC, "out of memory"); numSemaSets = 0; nextSemaKey = port * 1000; nextSemaNumber = SEMAS_PER_SET; /* force sema set alloc on 1st call */ on_shmem_exit(ReleaseSemaphores, 0); }
/* * PGReserveSemaphores --- initialize semaphore support * * This is called during postmaster start or shared memory reinitialization. * It should do whatever is needed to be able to support up to maxSemas * subsequent PGSemaphoreCreate calls. Also, if any system resources * are acquired here or in PGSemaphoreCreate, register an on_shmem_exit * callback to release them. * * The port number is passed for possible use as a key (for Posix, we use * it to generate the starting semaphore name). In a standalone backend, * zero will be passed. * * In the Posix implementation, we acquire semaphores on-demand; the * maxSemas parameter is just used to size the arrays. For unnamed * semaphores, there is an array of PGSemaphoreData structs in shared memory. * For named semaphores, we keep a postmaster-local array of sem_t pointers, * which we use for releasing the semphores when done. * (This design minimizes the dependency of postmaster shutdown on the * contents of shared memory, which a failed backend might have clobbered. * We can't do much about the possibility of sem_destroy() crashing, but * we don't have to expose the counters to other processes.) */ void PGReserveSemaphores(int maxSemas, int port) { #ifdef USE_NAMED_POSIX_SEMAPHORES mySemPointers = (sem_t **) malloc(maxSemas * sizeof(sem_t *)); if (mySemPointers == NULL) elog(PANIC, "out of memory"); #else /* * We must use ShmemAllocUnlocked(), since the spinlock protecting * ShmemAlloc() won't be ready yet. (This ordering is necessary when we * are emulating spinlocks with semaphores.) */ sharedSemas = (PGSemaphore) ShmemAllocUnlocked(PGSemaphoreShmemSize(maxSemas)); #endif numSems = 0; maxSems = maxSemas; nextSemKey = port * 1000; on_shmem_exit(ReleaseSemaphores, 0); }