/* * Initialize shared buffer pool * * This is called once during shared-memory initialization (either in the * postmaster, or in a standalone backend). */ void InitBufferPool(void) { bool foundBufs, foundDescs; BufferDescriptors = (BufferDesc *) ShmemInitStruct("Buffer Descriptors", NBuffers * sizeof(BufferDesc), &foundDescs); BufferBlocks = (char *) ShmemInitStruct("Buffer Blocks", NBuffers * (Size) BLCKSZ, &foundBufs); if (foundDescs || foundBufs) { /* both should be present or neither */ Assert(foundDescs && foundBufs); /* note: this path is only taken in EXEC_BACKEND case */ } else { BufferDesc *buf; int i; buf = BufferDescriptors; /* * Initialize all the buffer headers. */ for (i = 0; i < NBuffers; buf++, i++) { CLEAR_BUFFERTAG(buf->tag); buf->flags = 0; buf->usage_count = 0; buf->refcount = 0; buf->wait_backend_pid = 0; SpinLockInit(&buf->buf_hdr_lock); buf->buf_id = i; /* * Initially link all the buffers together as unused. Subsequent * management of this list is done by freelist.c. */ buf->freeNext = i + 1; buf->io_in_progress_lock = LWLockAssign(); buf->content_lock = LWLockAssign(); } /* Correct last entry of linked list */ BufferDescriptors[NBuffers - 1].freeNext = FREENEXT_END_OF_LIST; } /* Init other shared buffer-management stuff */ StrategyInitialize(!foundDescs); }
static void DtmInitialize() { bool found; static HASHCTL info; LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE); dtm = ShmemInitStruct("dtm", sizeof(DtmState), &found); if (!found) { dtm->hashLock = LWLockAssign(); dtm->xidLock = LWLockAssign(); dtm->nReservedXids = 0; dtm->minXid = InvalidTransactionId; dtm->nNodes = MMNodes; dtm->disabledNodeMask = 0; pg_atomic_write_u32(&dtm->nReceivers, 0); dtm->initialized = false; BgwPoolInit(&dtm->pool, MMExecutor, MMDatabaseName, MMQueueSize); RegisterXactCallback(DtmXactCallback, NULL); RegisterSubXactCallback(DtmSubXactCallback, NULL); } LWLockRelease(AddinShmemInitLock); info.keysize = sizeof(TransactionId); info.entrysize = sizeof(TransactionId); info.hash = dtm_xid_hash_fn; info.match = dtm_xid_match_fn; xid_in_doubt = ShmemInitHash( "xid_in_doubt", DTM_HASH_SIZE, DTM_HASH_SIZE, &info, HASH_ELEM | HASH_FUNCTION | HASH_COMPARE ); info.keysize = sizeof(TransactionId); info.entrysize = sizeof(LocalTransaction); info.hash = dtm_xid_hash_fn; info.match = dtm_xid_match_fn; local_trans = ShmemInitHash( "local_trans", DTM_HASH_SIZE, DTM_HASH_SIZE, &info, HASH_ELEM | HASH_FUNCTION | HASH_COMPARE ); MMDoReplication = true; TM = &DtmTM; }
/* * Allocate and initialize walsender-related shared memory. */ void ReplicationSlotsShmemInit(void) { bool found; if (max_replication_slots == 0) return; ReplicationSlotCtl = (ReplicationSlotCtlData *) ShmemInitStruct("ReplicationSlot Ctl", ReplicationSlotsShmemSize(), &found); if (!found) { int i; /* First time through, so initialize */ MemSet(ReplicationSlotCtl, 0, ReplicationSlotsShmemSize()); for (i = 0; i < max_replication_slots; i++) { ReplicationSlot *slot = &ReplicationSlotCtl->replication_slots[i]; /* everything else is zeroed by the memset above */ SpinLockInit(&slot->mutex); slot->io_in_progress_lock = LWLockAssign(); } } }
/* * shmem_startup hook: allocate or attach to shared memory, */ static void repmgr_shmem_startup(void) { bool found; if (prev_shmem_startup_hook) prev_shmem_startup_hook(); /* reset in case this is a restart within the postmaster */ shared_state = NULL; /* * Create or attach to the shared memory state, including hash table */ LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE); shared_state = ShmemInitStruct("repmgr shared state", sizeof(repmgrSharedState), &found); if (!found) { /* First time through ... */ shared_state->lock = LWLockAssign(); snprintf(shared_state->location, sizeof(shared_state->location), "%X/%X", 0, 0); } LWLockRelease(AddinShmemInitLock); }
void InitBufferPool () { int i; PrivateRefCount = (long *) malloc(NBuffers * sizeof(long)); // Altered to use regular memory BufferDescriptors = (BufferDesc *) malloc (NBuffers * sizeof(BufferDesc)); BufferBlocks = (char *) malloc (NBuffers * BLCKSZ); ShmemBase = BufferBlocks; // ShmemBase = (unsigned long) BufferBlocks; if (false) { } else { BufferDesc *buf; buf = BufferDescriptors; for (i = 0; i < NBuffers; buf++, i++) { CLEAR_BUFFERTAG(buf->tag); buf->flags = 0; buf->usage_count = 0; buf->refcount = 0; buf->wait_backend_pid = 0; buf->freeNext = i + 1; buf->buf_id = i; *((char *) MAKE_PTR(i * BLCKSZ)) = '#'; buf->io_in_progress_lock = LWLockAssign(); buf->content_lock = LWLockAssign(); } /* close the circular queue */ BufferDescriptors[NBuffers - 1].freeNext = -1; StrategyInitialize(true); } }
void SimpleLruInit(SlruCtl ctl, const char *name, LWLockId ctllock, const char *subdir) { SlruShared shared; bool found; shared = (SlruShared) ShmemInitStruct(name, SimpleLruShmemSize(), &found); if (!IsUnderPostmaster) { /* Initialize locks and shared memory area */ char *bufptr; int slotno; Assert(!found); memset(shared, 0, sizeof(SlruSharedData)); shared->ControlLock = ctllock; bufptr = (char *) shared + BUFFERALIGN(sizeof(SlruSharedData)); for (slotno = 0; slotno < NUM_SLRU_BUFFERS; slotno++) { shared->page_buffer[slotno] = bufptr; shared->page_status[slotno] = SLRU_PAGE_EMPTY; shared->page_lru_count[slotno] = 1; shared->buffer_locks[slotno] = LWLockAssign(); bufptr += BLCKSZ; } /* shared->latest_page_number will be set later */ } else Assert(found); /* * Initialize the unshared control struct, including directory path. We * assume caller set PagePrecedes. */ ctl->shared = shared; ctl->do_fsync = true; /* default behavior */ StrNCpy(ctl->Dir, subdir, sizeof(ctl->Dir)); }
/* * Probably the most important part of the startup - initializes the * memory in shared memory segment (creates and initializes the * SegmentInfo data structure). * * This is called from a shmem_startup_hook (see _PG_init). */ static void ispell_shmem_startup() { bool found = FALSE; char * segment; if (prev_shmem_startup_hook) prev_shmem_startup_hook(); elog(DEBUG1, "initializing shared ispell segment (size: %d B)", max_ispell_mem_size); /* * Create or attach to the shared memory state, including hash table */ LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE); segment = ShmemInitStruct(SEGMENT_NAME, max_ispell_mem_size, &found); /* Was the shared memory segment already initialized? */ if (! found) { memset(segment, 0, max_ispell_mem_size); segment_info = (SegmentInfo*)segment; segment_info->lock = LWLockAssign(); segment_info->firstfree = segment + MAXALIGN(sizeof(SegmentInfo)); segment_info->available = max_ispell_mem_size - (int)(segment_info->firstfree - segment); segment_info->lastReset = GetCurrentTimestamp(); elog(DEBUG1, "shared memory segment (shared ispell) successfully created"); } LWLockRelease(AddinShmemInitLock); }
void FtsShmemInit(void) { bool found; FtsControlBlock *shared; shared = (FtsControlBlock *)ShmemInitStruct("Fault Tolerance manager", FtsShmemSize(), &found); if (!shared) elog(FATAL, "FTS: could not initialize fault tolerance manager share memory"); /* Initialize locks and shared memory area */ ftsEnabled = &shared->ftsEnabled; ftsShutdownMaster = &shared->ftsShutdownMaster; ftsControlLock = shared->ControlLock; ftsReadOnlyFlag = &shared->ftsReadOnlyFlag; /* global RO state */ ftsAdminRequestedRO = &shared->ftsAdminRequestedRO; /* Admin request -- guc-controlled RO state */ ftsProbeInfo = &shared->fts_probe_info; if (!IsUnderPostmaster) { shared->ControlLock = LWLockAssign(); ftsControlLock = shared->ControlLock; /* initialize */ shared->ftsReadOnlyFlag = gp_set_read_only; shared->ftsAdminRequestedRO = gp_set_read_only; shared->fts_probe_info.fts_probePid = 0; shared->fts_probe_info.fts_pauseProbes = false; shared->fts_probe_info.fts_discardResults = false; shared->fts_probe_info.fts_statusVersion = 0; shared->ftsEnabled = true; /* ??? */ shared->ftsShutdownMaster = false; } }
static void shmem_startup() { bool found; /* reset in case this is a restart within the postmaster */ shared_mem = NULL; if (prev_shmem_startup_hook) prev_shmem_startup_hook(); LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE); shared_mem = ShmemInitStruct("pg_hibernator", sizeof(SharedState), &found); if (!found) { /* First time through */ shared_mem->lock = LWLockAssign(); } LWLockRelease(AddinShmemInitLock); }
/* * shmem_startup hook: allocate or attach to shared memory, * then load any pre-existing statistics from file. */ static void pgss_shmem_startup(void) { bool found; HASHCTL info; FILE *file; uint32 header; int32 num; int32 i; int query_size; int buffer_size; char *buffer = NULL; if (prev_shmem_startup_hook) prev_shmem_startup_hook(); /* reset in case this is a restart within the postmaster */ pgss = NULL; pgss_hash = NULL; /* * Create or attach to the shared memory state, including hash table */ LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE); pgss = ShmemInitStruct("pg_stat_statements", sizeof(pgssSharedState), &found); if (!found) { /* First time through ... */ pgss->lock = LWLockAssign(); pgss->query_size = pgstat_track_activity_query_size; } /* Be sure everyone agrees on the hash table entry size */ query_size = pgss->query_size; memset(&info, 0, sizeof(info)); info.keysize = sizeof(pgssHashKey); info.entrysize = offsetof(pgssEntry, query) +query_size; info.hash = pgss_hash_fn; info.match = pgss_match_fn; pgss_hash = ShmemInitHash("pg_stat_statements hash", pgss_max, pgss_max, &info, HASH_ELEM | HASH_FUNCTION | HASH_COMPARE); LWLockRelease(AddinShmemInitLock); /* * If we're in the postmaster (or a standalone backend...), set up a shmem * exit hook to dump the statistics to disk. */ if (!IsUnderPostmaster) on_shmem_exit(pgss_shmem_shutdown, (Datum) 0); /* * Attempt to load old statistics from the dump file, if this is the first * time through and we weren't told not to. */ if (found || !pgss_save) return; /* * Note: we don't bother with locks here, because there should be no other * processes running when this code is reached. */ file = AllocateFile(PGSS_DUMP_FILE, PG_BINARY_R); if (file == NULL) { if (errno == ENOENT) return; /* ignore not-found error */ goto error; } buffer_size = query_size; buffer = (char *) palloc(buffer_size); if (fread(&header, sizeof(uint32), 1, file) != 1 || header != PGSS_FILE_HEADER || fread(&num, sizeof(int32), 1, file) != 1) goto error; for (i = 0; i < num; i++) { pgssEntry temp; pgssEntry *entry; if (fread(&temp, offsetof(pgssEntry, mutex), 1, file) != 1) goto error; /* Encoding is the only field we can easily sanity-check */ if (!PG_VALID_BE_ENCODING(temp.key.encoding)) goto error; /* Previous incarnation might have had a larger query_size */ if (temp.key.query_len >= buffer_size) { buffer = (char *) repalloc(buffer, temp.key.query_len + 1); buffer_size = temp.key.query_len + 1; } if (fread(buffer, 1, temp.key.query_len, file) != temp.key.query_len) goto error; buffer[temp.key.query_len] = '\0'; /* Clip to available length if needed */ if (temp.key.query_len >= query_size) temp.key.query_len = pg_encoding_mbcliplen(temp.key.encoding, buffer, temp.key.query_len, query_size - 1); temp.key.query_ptr = buffer; /* make the hashtable entry (discards old entries if too many) */ entry = entry_alloc(&temp.key); /* copy in the actual stats */ entry->counters = temp.counters; } pfree(buffer); FreeFile(file); return; error: ereport(LOG, (errcode_for_file_access(), errmsg("could not read pg_stat_statement file \"%s\": %m", PGSS_DUMP_FILE))); if (buffer) pfree(buffer); if (file) FreeFile(file); /* If possible, throw away the bogus file; ignore any error */ unlink(PGSS_DUMP_FILE); }
/* * InitProcGlobal - * Initialize the global process table during postmaster or standalone * backend startup. * * We also create 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 * MaxConnections, max_worker_processes, or autovacuum_max_workers higher * than his kernel will support, he'll find out sooner rather than later. * * Another reason for creating semaphores here is that the semaphore * implementation typically requires us to create semaphores in the * postmaster, not in backends. * * Note: this is NOT called by individual backends under a postmaster, * not even in the EXEC_BACKEND case. The ProcGlobal and AuxiliaryProcs * pointers must be propagated specially for EXEC_BACKEND operation. */ void InitProcGlobal(void) { PGPROC *procs; PGXACT *pgxacts; int i, j; bool found; uint32 TotalProcs = MaxBackends + NUM_AUXILIARY_PROCS + max_prepared_xacts; /* Create the ProcGlobal shared structure */ ProcGlobal = (PROC_HDR *) ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &found); Assert(!found); /* * Initialize the data structures. */ ProcGlobal->spins_per_delay = DEFAULT_SPINS_PER_DELAY; ProcGlobal->freeProcs = NULL; ProcGlobal->autovacFreeProcs = NULL; ProcGlobal->bgworkerFreeProcs = NULL; ProcGlobal->startupProc = NULL; ProcGlobal->startupProcPid = 0; ProcGlobal->startupBufferPinWaitBufId = -1; ProcGlobal->walwriterLatch = NULL; ProcGlobal->checkpointerLatch = NULL; /* * Create and initialize all the PGPROC structures we'll need. There are * five separate consumers: (1) normal backends, (2) autovacuum workers * and the autovacuum launcher, (3) background workers, (4) auxiliary * processes, and (5) prepared transactions. Each PGPROC structure is * dedicated to exactly one of these purposes, and they do not move * between groups. */ procs = (PGPROC *) ShmemAlloc(TotalProcs * sizeof(PGPROC)); ProcGlobal->allProcs = procs; /* XXX allProcCount isn't really all of them; it excludes prepared xacts */ ProcGlobal->allProcCount = MaxBackends + NUM_AUXILIARY_PROCS; elog(DEBUG3, "InitProcGlobal of size %d :: TID : %d", TotalProcs, GetBackendThreadId()); if (!procs) ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); MemSet(procs, 0, TotalProcs * sizeof(PGPROC)); /* * Also allocate a separate array of PGXACT structures. This is separate * from the main PGPROC array so that the most heavily accessed data is * stored contiguously in memory in as few cache lines as possible. This * provides significant performance benefits, especially on a * multiprocessor system. There is one PGXACT structure for every PGPROC * structure. */ pgxacts = (PGXACT *) ShmemAlloc(TotalProcs * sizeof(PGXACT)); MemSet(pgxacts, 0, TotalProcs * sizeof(PGXACT)); ProcGlobal->allPgXact = pgxacts; for (i = 0; i < TotalProcs; i++) { /* Common initialization for all PGPROCs, regardless of type. */ /* * Set up per-PGPROC semaphore, latch, and backendLock. Prepared xact * dummy PGPROCs don't need these though - they're never associated * with a real process */ if (i < MaxBackends + NUM_AUXILIARY_PROCS) { PGSemaphoreCreate(&(procs[i].sem)); InitSharedLatch(&(procs[i].procLatch)); procs[i].backendLock = LWLockAssign(); } procs[i].pgprocno = i; /* * Newly created PGPROCs for normal backends, autovacuum and bgworkers * 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. PGPROCs for prepared transactions are added to a * free list by TwoPhaseShmemInit(). */ if (i < MaxConnections) { /* PGPROC for normal backend, add to freeProcs list */ procs[i].links.next = (SHM_QUEUE *) ProcGlobal->freeProcs; ProcGlobal->freeProcs = &procs[i]; //elog(DEBUG3, "freeProcs %d = %p", i, ProcGlobal->freeProcs); //Assert(ShmemAddrIsValid(ProcGlobal->freeProcs)); } else if (i < MaxConnections + autovacuum_max_workers + 1) { /* PGPROC for AV launcher/worker, add to autovacFreeProcs list */ procs[i].links.next = (SHM_QUEUE *) ProcGlobal->autovacFreeProcs; ProcGlobal->autovacFreeProcs = &procs[i]; } else if (i < MaxBackends) { /* PGPROC for bgworker, add to bgworkerFreeProcs list */ procs[i].links.next = (SHM_QUEUE *) ProcGlobal->bgworkerFreeProcs; ProcGlobal->bgworkerFreeProcs = &procs[i]; } /* Initialize myProcLocks[] shared memory queues. */ for (j = 0; j < NUM_LOCK_PARTITIONS; j++) SHMQueueInit(&(procs[i].myProcLocks[j])); } /* * Save pointers to the blocks of PGPROC structures reserved for auxiliary * processes and prepared transactions. */ AuxiliaryProcs = &procs[MaxBackends]; PreparedXactProcs = &procs[MaxBackends + NUM_AUXILIARY_PROCS]; /* Create ProcStructLock spinlock, too */ ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t)); SpinLockInit(ProcStructLock); }
void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns, LWLockId ctllock, const char *subdir) { SlruShared shared; bool found; shared = (SlruShared) ShmemInitStruct(name, SimpleLruShmemSize(nslots, nlsns), &found); if (!IsUnderPostmaster) { /* Initialize locks and shared memory area */ char *ptr; Size offset; int slotno; Assert(!found); memset(shared, 0, sizeof(SlruSharedData)); shared->ControlLock = ctllock; shared->num_slots = nslots; shared->lsn_groups_per_page = nlsns; shared->cur_lru_count = 0; /* shared->latest_page_number will be set later */ ptr = (char *) shared; offset = MAXALIGN(sizeof(SlruSharedData)); shared->page_buffer = (char **) (ptr + offset); offset += MAXALIGN(nslots * sizeof(char *)); shared->page_status = (SlruPageStatus *) (ptr + offset); offset += MAXALIGN(nslots * sizeof(SlruPageStatus)); shared->page_dirty = (bool *) (ptr + offset); offset += MAXALIGN(nslots * sizeof(bool)); shared->page_number = (int *) (ptr + offset); offset += MAXALIGN(nslots * sizeof(int)); shared->page_lru_count = (int *) (ptr + offset); offset += MAXALIGN(nslots * sizeof(int)); shared->buffer_locks = (LWLockId *) (ptr + offset); offset += MAXALIGN(nslots * sizeof(LWLockId)); if (nlsns > 0) { shared->group_lsn = (XLogRecPtr *) (ptr + offset); offset += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); } ptr += BUFFERALIGN(offset); for (slotno = 0; slotno < nslots; slotno++) { shared->page_buffer[slotno] = ptr; shared->page_status[slotno] = SLRU_PAGE_EMPTY; shared->page_dirty[slotno] = false; shared->page_lru_count[slotno] = 0; shared->buffer_locks[slotno] = LWLockAssign(); ptr += BLCKSZ; } } else Assert(found); /* * Initialize the unshared control struct, including directory path. We * assume caller set PagePrecedes. */ ctl->shared = shared; ctl->do_fsync = true; /* default behavior */ StrNCpy(ctl->Dir, subdir, sizeof(ctl->Dir)); }
/* This is probably the most important part - allocates the shared * segment, initializes it etc. */ static void pg_record_shmem_startup() { bool found = FALSE; char *segment = NULL; int i; off_t size; char filename[MAX_FILE_NAME]; if (prev_shmem_startup_hook) prev_shmem_startup_hook(); /* * Create or attach to the shared memory state, including hash table */ LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE); segment = ShmemInitStruct(SEGMENT_NAME, SEGMENT_SIZE, &found); /* set the pointers */ info = (info_t*)(segment); log_file = (log_file_t*)(segment + sizeof(info_t)); query_buffer = (buffer_t*)(segment + sizeof(info_t) + sizeof(log_file_t)); elog(DEBUG1, "initializing query buffer segment (size: %lu B)", SEGMENT_SIZE); if (! found) { /* First time through ... */ info->lock = LWLockAssign(); log_file->lock = LWLockAssign(); query_buffer->lock = LWLockAssign(); query_buffer->next = 0; max_file_size *= BLCKSZ; buffer_size *= BLCKSZ; info->enabled = enabled; if (base_filename == NULL) { snprintf(log_file->base_filename, 255, "%s", DEFAULT_DUMP_FILE); } else { snprintf(log_file->base_filename, 255, "%s", base_filename); } memset(query_buffer->buffer, 0, (buffer_size)*sizeof(char)); elog(DEBUG1, "shared memory segment (query buffer) successfully created"); /* use the first file */ log_file->file_number = 0; log_file->file_bytes = 0; format_filename(log_file->curr_filename, log_file->base_filename, log_file->file_number, MAX_FILE_NAME); /* find the last file (iterate) */ for (i = 0; i < max_files; i++) { format_filename(filename, log_file->base_filename, i, MAX_FILE_NAME); if (! file_exists(filename, &size)) { break; } strcpy(log_file->curr_filename, filename); /* use the last found file */ log_file->file_number = i; log_file->file_bytes = size; } } LWLockRelease(AddinShmemInitLock); /* * If we're in the postmaster (or a standalone backend...), set up a shmem * exit hook to dump the statistics to disk. */ if (!IsUnderPostmaster) on_shmem_exit(pg_record_shmem_shutdown, (Datum) 0); }
/* * Initialize shared buffer pool * * This is called once during shared-memory initialization (either in the * postmaster, or in a standalone backend). */ void InitBufferPool(void) { char *BufferBlocks; bool foundBufs, foundDescs; int i; Data_Descriptors = NBuffers; Free_List_Descriptor = Data_Descriptors; Lookup_List_Descriptor = Data_Descriptors + 1; Num_Descriptors = Data_Descriptors + 1; /* * It's probably not really necessary to grab the lock --- if there's * anyone else attached to the shmem at this point, we've got * problems. */ LWLockAcquire(BufMgrLock, LW_EXCLUSIVE); #ifdef BMTRACE CurTraceBuf = (long *) ShmemInitStruct("Buffer trace", (BMT_LIMIT * sizeof(bmtrace)) + sizeof(long), &foundDescs); if (!foundDescs) MemSet(CurTraceBuf, 0, (BMT_LIMIT * sizeof(bmtrace)) + sizeof(long)); TraceBuf = (bmtrace *) & (CurTraceBuf[1]); #endif BufferDescriptors = (BufferDesc *) ShmemInitStruct("Buffer Descriptors", Num_Descriptors * sizeof(BufferDesc), &foundDescs); BufferBlocks = (char *) ShmemInitStruct("Buffer Blocks", NBuffers * BLCKSZ, &foundBufs); if (foundDescs || foundBufs) { /* both should be present or neither */ Assert(foundDescs && foundBufs); } else { BufferDesc *buf; char *block; buf = BufferDescriptors; block = BufferBlocks; /* * link the buffers into a circular, doubly-linked list to * initialize free list, and initialize the buffer headers. Still * don't know anything about replacement strategy in this file. */ for (i = 0; i < Data_Descriptors; block += BLCKSZ, buf++, i++) { Assert(ShmemIsValid((unsigned long) block)); buf->freeNext = i + 1; buf->freePrev = i - 1; CLEAR_BUFFERTAG(&(buf->tag)); buf->buf_id = i; buf->data = MAKE_OFFSET(block); buf->flags = (BM_DELETED | BM_FREE | BM_VALID); buf->refcount = 0; buf->io_in_progress_lock = LWLockAssign(); buf->cntx_lock = LWLockAssign(); buf->cntxDirty = false; buf->wait_backend_id = 0; } /* close the circular queue */ BufferDescriptors[0].freePrev = Data_Descriptors - 1; BufferDescriptors[Data_Descriptors - 1].freeNext = 0; } /* Init other shared buffer-management stuff */ InitBufTable(); InitFreeList(!foundDescs); LWLockRelease(BufMgrLock); }
/* * Initialize shared buffer pool * * This is called once during shared-memory initialization (either in the * postmaster, or in a standalone backend). */ void InitBufferPool(void) { char *BufferBlocks; bool foundBufs, foundDescs; int i; BufferDescriptors = (BufferDesc *) ShmemInitStruct("Buffer Descriptors", NBuffers * sizeof(BufferDesc), &foundDescs); BufferBlocks = (char *) ShmemInitStruct("Buffer Blocks", NBuffers * BLCKSZ, &foundBufs); if (foundDescs || foundBufs) { /* both should be present or neither */ Assert(foundDescs && foundBufs); } else { BufferDesc *buf; char *block; /* * It's probably not really necessary to grab the lock --- if * there's anyone else attached to the shmem at this point, we've * got problems. */ LWLockAcquire(BufMgrLock, LW_EXCLUSIVE); buf = BufferDescriptors; block = BufferBlocks; /* * Initialize all the buffer headers. */ for (i = 0; i < NBuffers; block += BLCKSZ, buf++, i++) { Assert(ShmemIsValid((unsigned long) block)); /* * The bufNext fields link together all totally-unused buffers. * Subsequent management of this list is done by * StrategyGetBuffer(). */ buf->bufNext = i + 1; CLEAR_BUFFERTAG(buf->tag); buf->buf_id = i; buf->data = MAKE_OFFSET(block); buf->flags = 0; buf->refcount = 0; buf->io_in_progress_lock = LWLockAssign(); buf->cntx_lock = LWLockAssign(); buf->cntxDirty = false; buf->wait_backend_id = 0; } /* Correct last entry of linked list */ BufferDescriptors[NBuffers - 1].bufNext = -1; LWLockRelease(BufMgrLock); } /* Init other shared buffer-management stuff */ StrategyInitialize(!foundDescs); }
bool ora_lock_shmem(size_t size, int max_pipes, int max_events, int max_locks, bool reset) { int i; bool found; sh_memory *sh_mem; if (pipes == NULL) { sh_mem = ShmemInitStruct("dbms_pipe", size, &found); if (sh_mem == NULL) ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), errdetail("Failed while allocation block %lu bytes in shared memory.", (unsigned long) size))); if (!found) { #if PG_VERSION_NUM >= 90600 sh_mem->tranche_id = LWLockNewTrancheId(); LWLockInitialize(&sh_mem->shmem_lock, sh_mem->tranche_id); { #if PG_VERSION_NUM >= 100000 LWLockRegisterTranche(sh_mem->tranche_id, "orafce"); #else static LWLockTranche tranche; tranche.name = "orafce"; tranche.array_base = &sh_mem->shmem_lock; tranche.array_stride = sizeof(LWLock); LWLockRegisterTranche(sh_mem->tranche_id, &tranche); #endif shmem_lockid = &sh_mem->shmem_lock; } #else shmem_lockid = sh_mem->shmem_lockid = LWLockAssign(); #endif LWLockAcquire(shmem_lockid, LW_EXCLUSIVE); sh_mem->size = size - sh_memory_size; ora_sinit(sh_mem->data, size, true); pipes = sh_mem->pipes = ora_salloc(max_pipes*sizeof(pipe)); sid = sh_mem->sid = 1; for (i = 0; i < max_pipes; i++) pipes[i].is_valid = false; events = sh_mem->events = ora_salloc(max_events*sizeof(alert_event)); locks = sh_mem->locks = ora_salloc(max_locks*sizeof(alert_lock)); for (i = 0; i < max_events; i++) { events[i].event_name = NULL; events[i].max_receivers = 0; events[i].receivers = NULL; events[i].messages = NULL; } for (i = 0; i < max_locks; i++) { locks[i].sid = -1; locks[i].echo = NULL; } } else if (pipes == NULL) { #if PG_VERSION_NUM >= 90600 #if PG_VERSION_NUM >= 100000 LWLockRegisterTranche(sh_mem->tranche_id, "orafce"); #else static LWLockTranche tranche; tranche.name = "orafce"; tranche.array_base = &sh_mem->shmem_lock; tranche.array_stride = sizeof(LWLock); LWLockRegisterTranche(sh_mem->tranche_id, &tranche); #endif shmem_lockid = &sh_mem->shmem_lock; #else shmem_lockid = sh_mem->shmem_lockid; #endif pipes = sh_mem->pipes; LWLockAcquire(shmem_lockid, LW_EXCLUSIVE); ora_sinit(sh_mem->data, sh_mem->size, reset); sid = ++(sh_mem->sid); events = sh_mem->events; locks = sh_mem->locks; } } else { LWLockAcquire(shmem_lockid, LW_EXCLUSIVE); } return pipes != NULL; }
void FtsShmemInit(void) { bool found; FtsControlBlock *shared; shared = (FtsControlBlock *)ShmemInitStruct("Fault Tolerance manager", FtsShmemSize(), &found); if (!shared) elog(FATAL, "FTS: could not initialize fault tolerance manager share memory"); /* Initialize locks and shared memory area */ ftsEnabled = &shared->ftsEnabled; ftsShutdownMaster = &shared->ftsShutdownMaster; ftsControlLock = shared->ControlLock; ftsReadOnlyFlag = &shared->ftsReadOnlyFlag; /* global RO state */ ftsAdminRequestedRO = &shared->ftsAdminRequestedRO; /* Admin request -- guc-controlled RO state */ ftsQDMirrorLock = shared->ftsQDMirrorLock; ftsQDMirrorUpdateConfigLock = shared->ftsQDMirrorUpdateConfigLock; ftsQDMirrorInfo = &shared->ftsQDMirror; ftsProbeInfo = &shared->fts_probe_info; if (!IsUnderPostmaster) { shared->ControlLock = LWLockAssign(); ftsControlLock = shared->ControlLock; shared->ftsQDMirrorLock = LWLockAssign(); ftsQDMirrorLock = shared->ftsQDMirrorLock; shared->ftsQDMirrorUpdateConfigLock = LWLockAssign(); ftsQDMirrorUpdateConfigLock = shared->ftsQDMirrorUpdateConfigLock; ftsQDMirrorInfo->configurationChecked = false; ftsQDMirrorInfo->state = QDMIRROR_STATE_NONE; ftsQDMirrorInfo->updateMask = QDMIRROR_UPDATEMASK_NONE; ftsQDMirrorInfo->disabledReason = QDMIRROR_DISABLEDREASON_NONE; memset(&ftsQDMirrorInfo->lastLogTimeVal, 0, sizeof(struct timeval)); strcpy(ftsQDMirrorInfo->errorMessage, ""); ftsQDMirrorInfo->haveNewCheckpointLocation = false; memset(&ftsQDMirrorInfo->newCheckpointLocation, 0, sizeof(XLogRecPtr)); memset(ftsQDMirrorInfo->name, 0, sizeof(ftsQDMirrorInfo->name)); ftsQDMirrorInfo->port = 0; ftsQDMirrorInfo->QDMirroringNotSynchronizedWarningGiven = false; /* initialize */ shared->ftsReadOnlyFlag = gp_set_read_only; shared->ftsAdminRequestedRO = gp_set_read_only; shared->fts_probe_info.fts_probePid = 0; shared->fts_probe_info.fts_pauseProbes = false; shared->fts_probe_info.fts_discardResults = false; shared->fts_probe_info.fts_statusVersion = 0; shared->ftsEnabled = true; /* ??? */ shared->ftsShutdownMaster = false; } }