void storageAddCapabilities (nat from, nat to) { nat n, g, i; if (from > 0) { nurseries = stgReallocBytes(nurseries, to * sizeof(struct nursery_), "storageAddCapabilities"); } else { nurseries = stgMallocBytes(to * sizeof(struct nursery_), "storageAddCapabilities"); } // we've moved the nurseries, so we have to update the rNursery // pointers from the Capabilities. for (i = 0; i < to; i++) { capabilities[i].r.rNursery = &nurseries[i]; } /* The allocation area. Policy: keep the allocation area * small to begin with, even if we have a large suggested heap * size. Reason: we're going to do a major collection first, and we * don't want it to be a big one. This vague idea is borne out by * rigorous experimental evidence. */ allocNurseries(from, to); // allocate a block for each mut list for (n = from; n < to; n++) { for (g = 1; g < RtsFlags.GcFlags.generations; g++) { capabilities[n].mut_lists[g] = allocBlock(); } } initGcThreads(from, to); }
void storageAddCapabilities (uint32_t from, uint32_t to) { uint32_t n, g, i, new_n_nurseries; if (RtsFlags.GcFlags.nurseryChunkSize == 0) { new_n_nurseries = to; } else { memcount total_alloc = to * RtsFlags.GcFlags.minAllocAreaSize; new_n_nurseries = stg_max(to, total_alloc / RtsFlags.GcFlags.nurseryChunkSize); } if (from > 0) { nurseries = stgReallocBytes(nurseries, new_n_nurseries * sizeof(struct nursery_), "storageAddCapabilities"); } else { nurseries = stgMallocBytes(new_n_nurseries * sizeof(struct nursery_), "storageAddCapabilities"); } // we've moved the nurseries, so we have to update the rNursery // pointers from the Capabilities. for (i = 0; i < to; i++) { capabilities[i]->r.rNursery = &nurseries[i]; } /* The allocation area. Policy: keep the allocation area * small to begin with, even if we have a large suggested heap * size. Reason: we're going to do a major collection first, and we * don't want it to be a big one. This vague idea is borne out by * rigorous experimental evidence. */ allocNurseries(n_nurseries, new_n_nurseries); n_nurseries = new_n_nurseries; /* * Assign each of the new capabilities a nursery. Remember to start from * next_nursery, because we may have already consumed some of the earlier * nurseries. */ assignNurseriesToCapabilities(from,to); // allocate a block for each mut list for (n = from; n < to; n++) { for (g = 1; g < RtsFlags.GcFlags.generations; g++) { capabilities[n]->mut_lists[g] = allocBlockOnNode(capNoToNumaNode(n)); } } #if defined(THREADED_RTS) && defined(llvm_CC_FLAVOR) && (CC_SUPPORTS_TLS == 0) newThreadLocalKey(&gctKey); #endif initGcThreads(from, to); }
void initStorage( void ) { nat g, n; if (generations != NULL) { // multi-init protection return; } initMBlocks(); /* Sanity check to make sure the LOOKS_LIKE_ macros appear to be * doing something reasonable. */ /* We use the NOT_NULL variant or gcc warns that the test is always true */ ASSERT(LOOKS_LIKE_INFO_PTR_NOT_NULL((StgWord)&stg_BLOCKING_QUEUE_CLEAN_info)); ASSERT(LOOKS_LIKE_CLOSURE_PTR(&stg_dummy_ret_closure)); ASSERT(!HEAP_ALLOCED(&stg_dummy_ret_closure)); if (RtsFlags.GcFlags.maxHeapSize != 0 && RtsFlags.GcFlags.heapSizeSuggestion > RtsFlags.GcFlags.maxHeapSize) { RtsFlags.GcFlags.maxHeapSize = RtsFlags.GcFlags.heapSizeSuggestion; } if (RtsFlags.GcFlags.maxHeapSize != 0 && RtsFlags.GcFlags.minAllocAreaSize > RtsFlags.GcFlags.maxHeapSize) { errorBelch("maximum heap size (-M) is smaller than minimum alloc area size (-A)"); RtsFlags.GcFlags.minAllocAreaSize = RtsFlags.GcFlags.maxHeapSize; } initBlockAllocator(); #if defined(THREADED_RTS) initMutex(&sm_mutex); #endif ACQUIRE_SM_LOCK; /* allocate generation info array */ generations = (generation *)stgMallocBytes(RtsFlags.GcFlags.generations * sizeof(struct generation_), "initStorage: gens"); /* Initialise all generations */ for(g = 0; g < RtsFlags.GcFlags.generations; g++) { initGeneration(&generations[g], g); } /* A couple of convenience pointers */ g0 = &generations[0]; oldest_gen = &generations[RtsFlags.GcFlags.generations-1]; nurseries = stgMallocBytes(n_capabilities * sizeof(struct nursery_), "initStorage: nurseries"); /* Set up the destination pointers in each younger gen. step */ for (g = 0; g < RtsFlags.GcFlags.generations-1; g++) { generations[g].to = &generations[g+1]; } oldest_gen->to = oldest_gen; /* The oldest generation has one step. */ if (RtsFlags.GcFlags.compact || RtsFlags.GcFlags.sweep) { if (RtsFlags.GcFlags.generations == 1) { errorBelch("WARNING: compact/sweep is incompatible with -G1; disabled"); } else { oldest_gen->mark = 1; if (RtsFlags.GcFlags.compact) oldest_gen->compact = 1; } } generations[0].max_blocks = 0; /* The allocation area. Policy: keep the allocation area * small to begin with, even if we have a large suggested heap * size. Reason: we're going to do a major collection first, and we * don't want it to be a big one. This vague idea is borne out by * rigorous experimental evidence. */ allocNurseries(); weak_ptr_list = NULL; caf_list = END_OF_STATIC_LIST; revertible_caf_list = END_OF_STATIC_LIST; /* initialise the allocate() interface */ large_alloc_lim = RtsFlags.GcFlags.minAllocAreaSize * BLOCK_SIZE_W; exec_block = NULL; #ifdef THREADED_RTS initSpinLock(&gc_alloc_block_sync); whitehole_spin = 0; #endif N = 0; // allocate a block for each mut list for (n = 0; n < n_capabilities; n++) { for (g = 1; g < RtsFlags.GcFlags.generations; g++) { capabilities[n].mut_lists[g] = allocBlock(); } } initGcThreads(); IF_DEBUG(gc, statDescribeGens()); RELEASE_SM_LOCK; }