bool ProcBegin( void ) /***************************/ /* process a new overlay area */ { section *oldsect; file_list **oldflist; section *sect; LinkState |= FMT_SPECIFIED; // she must want DOS mode. if( ( OvlLevel > 0 ) && FmtData.u.dos.dynamic ) { oldsect = NULL; oldflist = NULL; CmdFlags &= ~CF_AUTOSECTION; // merge old area with this. } else { oldsect = CurrSect; oldflist = CurrFList; sect = NewSection(); if( LinkFlags & ANY_DBI_FLAG ) { DBISectInit( sect ); } NewArea( sect ); sect->relocs = SECT_ALREADY_MADE; CurrSect = sect; CurrFList = §->files; } OvlLevel++; while( ProcOne( Sections, SEP_NO, FALSE ) != FALSE ) {} // NULL LOOP if( ( OvlLevel == 0 ) || !FmtData.u.dos.dynamic ) { CurrFList = oldflist; CurrSect = oldsect; } return( TRUE ); }
/* void* allocmem(AllocPool *pool, int32 size); void* allocmem(AllocPool *pool, int32 size) { return pool->Alloc(size); } void* reallocmem(AllocPool *pool, void* ptr, int32 size); void* reallocmem(AllocPool *pool, void* ptr, int32 size) { return pool->Realloc(ptr, size); } void freemem(AllocPool *pool, void* ptr); void freemem(AllocPool *pool, void* ptr) { pool->Free(ptr); } */ void AllocPool::InitAlloc() { if (mAreaInitSize == 0) return; /* alloc initial area */ NewArea(mAreaInitSize); /* get chunk */ AllocAreaPtr area = mAreas; AllocChunkPtr chunk = &area->mChunk; LinkFree(chunk); check_pool(); }
void C4LSectors::Update(C4Object *pObj, C4ObjectList *pMainList) { assert(Sectors); // Not added yet? if (pObj->Area.IsNull()) { Add(pObj, pMainList); return; } C4LSector *pOld, *pNew; if (pObj->old_x != pObj->GetX() || pObj->old_y != pObj->GetY()) { // Get involved sectors pOld = SectorAt(pObj->old_x, pObj->old_y); pNew = SectorAt(pObj->GetX(), pObj->GetY()); if (pOld != pNew) { pOld->Objects.Remove(pObj); pNew->Objects.Add(pObj, C4ObjectList::stMain, pMainList); } // Save position pObj->old_x = pObj->GetX(); pObj->old_y = pObj->GetY(); } // New area C4LArea NewArea(this, pObj); if (pObj->Area == NewArea) return; // Remove from all old sectors in shape area for (pOld = pObj->Area.First(); pOld; pOld = pObj->Area.Next(pOld)) if (!NewArea.Contains(pOld)) pOld->ObjectShapes.Remove(pObj); // Add to all new sectors in shape area for (pNew = NewArea.First(); pNew; pNew = NewArea.Next(pNew)) if (!pObj->Area.Contains(pNew)) { pNew->ObjectShapes.Add(pObj, C4ObjectList::stMain, pMainList); } // Update area pObj->Area = NewArea; if (Config.General.DebugRec) pObj->Area.DebugRec(pObj, 'U'); }
void* AllocPool::Alloc(size_t inReqSize) { #ifdef DISABLE_MEMORY_POOLS return malloc(inReqSize); #endif // OK it has a lot of gotos, but these remove a whole lot of common code // that was obfuscating the original version of this function. // So here I am choosing the OnceAndOnlyOnce principle over the caveats on gotos. // The gotos only jump forward and only to the exit paths of the function // The old bin block scheme has been replaced by 4 x 32 bit words so that each bin has a bit // and the next bin is found using a count leading zeroes instruction. Much faster. // Also now each bin's flag can be kept accurate. This simplifies the searching code quite a bit. // Also fwiw, changed 'victim' in the original code to 'candidate'. 'victim' just bothered me. AllocChunkPtr candidate; /* inspected/selected chunk */ size_t candidate_size; /* its size */ AllocChunkPtr remainder; /* remainder from a split */ int32 remainder_size; /* its size */ AllocAreaPtr area; size_t areaSize; size_t size = RequestToSize(inReqSize); int index = BinIndex(size); assert(index < 128); AllocChunkPtr bin = mBins + index; check_pool(); /* Check for exact match in a bin */ if (index < kMaxSmallBin) { /* Faster version for small requests */ /* No traversal or size check necessary for small bins. */ candidate = bin->Prev(); /* Also scan the next one, since it would have a remainder < kMinAllocSize */ if (candidate == bin) candidate = (++bin)->Prev(); if (candidate != bin) { candidate_size = candidate->Size(); goto found_exact_fit; } index += 2; /* Set for bin scan below. We've already scanned 2 bins. */ } else { for (candidate = bin->Prev(); candidate != bin; candidate = candidate->Prev()) { candidate_size = candidate->Size(); remainder_size = (int)(candidate_size - size); if (remainder_size >= (int32)kMinAllocSize) { /* too big */ --index; /* adjust to rescan below after checking last remainder */ break; } else if (remainder_size >= 0) { /* exact fit */ goto found_exact_fit; } } ++index; } for(; (index = NextFullBin(index)) >= 0; ++index) { bin = mBins + index; /* Find and use first big enough chunk ... */ for (candidate = bin->Prev(); candidate != bin; candidate = candidate->Prev()) { candidate_size = candidate->Size(); remainder_size = (int)(candidate_size - size); if (remainder_size >= (int32)kMinAllocSize) { /* split */ UnlinkFree(candidate); goto found_bigger_fit; } else if (remainder_size >= 0) goto found_exact_fit; } } check_pool(); if (mAreaMoreSize == 0) { /* pool has a non-growable area */ if (mAreas != NULL /* fixed size area exhausted */ || size > mAreaInitSize) /* too big anyway */ goto found_nothing; areaSize = mAreaInitSize; goto split_new_area; } if (size > mAreaMoreSize) { areaSize = size; goto whole_new_area; } else { areaSize = mAreaMoreSize; goto split_new_area; } // exit paths: found_nothing: //ipostbuf("alloc failed. size: %d\n", inReqSize); throw std::runtime_error("alloc failed, increase server's memory allocation (e.g. via ServerOptions)"); whole_new_area: //ipostbuf("whole_new_area\n"); area = NewArea(areaSize); if (!area) return 0; candidate = &area->mChunk; candidate_size = candidate->Size(); goto return_chunk; split_new_area: //ipostbuf("split_new_area\n"); area = NewArea(areaSize); if (!area) return 0; candidate = &area->mChunk; candidate_size = candidate->Size(); remainder_size = (int)(areaSize - size); // FALL THROUGH found_bigger_fit: //ipostbuf("found_bigger_fit\n"); remainder = candidate->ChunkAtOffset(size); remainder->SetSizeFree(remainder_size); candidate_size -= remainder_size; LinkFree(remainder); goto return_chunk; found_exact_fit: check_pool(); UnlinkFree(candidate); // FALL THROUGH return_chunk: candidate->SetSizeInUse(candidate_size); check_malloced_chunk(candidate, candidate_size); check_pool(); garbage_fill(candidate); return candidate->ToPtr(); }