Ejemplo n.º 1
0
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 = &sect->files;
    }
    OvlLevel++;
    while( ProcOne( Sections, SEP_NO, FALSE ) != FALSE ) {}  // NULL LOOP
    if( ( OvlLevel == 0 ) || !FmtData.u.dos.dynamic ) {
        CurrFList = oldflist;
        CurrSect = oldsect;
    }
    return( TRUE );
}
Ejemplo n.º 2
0
/*
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();
}
Ejemplo n.º 3
0
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');
}
Ejemplo n.º 4
0
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();
}