C++程序  |  416行  |  12.21 KB

/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* ---- includes ----------------------------------------------------------- */

#include "b_BasicEm/MemSeg.h"
#include "b_BasicEm/Functions.h"
#include "b_BasicEm/Context.h"

/* ------------------------------------------------------------------------- */

/* ========================================================================= */
/*                                                                           */
/* ---- \ghd{ auxiliary functions } ---------------------------------------- */
/*                                                                           */
/* ========================================================================= */

/* ------------------------------------------------------------------------- */

/* ========================================================================= */
/*                                                                           */
/* ---- \ghd{ constructor / destructor } ----------------------------------- */
/*                                                                           */
/* ========================================================================= */

/* ------------------------------------------------------------------------- */

void bbs_MemSeg_init( struct bbs_Context* cpA, 
					  struct bbs_MemSeg* ptrA )
{
	ptrA->memPtrE = NULL;
	ptrA->sizeE = 0;
	ptrA->allocIndexE = 0;
	ptrA->sharedE = FALSE;
	ptrA->idE = 0;
	ptrA->dynMemManagerPtrE = NULL;
}

/* ------------------------------------------------------------------------- */

void bbs_MemSeg_exit( struct bbs_Context* cpA, 
					  struct bbs_MemSeg* ptrA )
{
	ptrA->memPtrE = NULL;
	ptrA->sizeE = 0;
	ptrA->allocIndexE = 0;
	ptrA->sharedE = FALSE;
	ptrA->idE = 0;
	ptrA->dynMemManagerPtrE = NULL;
}

/* ------------------------------------------------------------------------- */

/* ========================================================================= */
/*                                                                           */
/* ---- \ghd{ operators } -------------------------------------------------- */
/*                                                                           */
/* ========================================================================= */

/* ------------------------------------------------------------------------- */

/* ========================================================================= */
/*                                                                           */
/* ---- \ghd{ query functions } -------------------------------------------- */
/*                                                                           */
/* ========================================================================= */

/* ------------------------------------------------------------------------- */

uint32 bbs_MemSeg_availableSize( struct bbs_Context* cpA, 
								 const struct bbs_MemSeg* ptrA )
{
	if( ptrA->dynMemManagerPtrE == NULL )
	{
		return ( ptrA->sizeE == ptrA->allocIndexE ) ? 0 : ptrA->sizeE - ptrA->allocIndexE - 2 * ptrA->sharedE;
	}
	else
	{
		return 0xFFFFFFFF;
	}
}

/* ------------------------------------------------------------------------- */

uint32 bbs_MemSeg_allocatedSize( struct bbs_Context* cpA, 
								 const struct bbs_MemSeg* ptrA )
{
	if( ptrA->dynMemManagerPtrE == NULL )
	{
		return ptrA->allocIndexE;
	}
	else
	{
		return bbs_DynMemManager_allocatedSize( cpA, ptrA->dynMemManagerPtrE );
	}
}

/* ------------------------------------------------------------------------- */

uint32 bbs_MemSeg_usedSize( struct bbs_Context* cpA, 
						    const struct bbs_MemSeg* ptrA )
{
	if( ptrA->dynMemManagerPtrE == NULL )
	{
		if( ptrA->sharedE )
		{
			return ptrA->allocIndexE;
		}
		else
		{
			uint32 indexL = 0;
			uint32 countL = 0;
			while( indexL < ptrA->allocIndexE )
			{
				uint32 sizeL = *( uint32* )( ptrA->memPtrE + indexL );
				indexL += ( sizeL & 0xFFFFFFFE );
				if( ( sizeL & 1 ) == 0 )
				{
					countL += sizeL - 2;
				}
			}
			return countL;
		}
	}
	else
	{
		return bbs_MemSeg_allocatedSize( cpA, ptrA );
	}
}

/* ------------------------------------------------------------------------- */

uint32 bbs_MemSeg_blocks( struct bbs_Context* cpA, 
						  const struct bbs_MemSeg* ptrA )
{
	uint32 indexL = 0;
	uint32 countL = 0;

	if( ptrA->sharedE ) return 0;

	while( indexL < ptrA->allocIndexE )
	{
		uint32 sizeL = *( uint32* )( ptrA->memPtrE + indexL );
		indexL += ( sizeL & 0xFFFFFFFE );
		countL++;
	}
	return countL;
}

/* ------------------------------------------------------------------------- */

uint32 bbs_MemSeg_usedBlocks( struct bbs_Context* cpA, 
							  const struct bbs_MemSeg* ptrA )
{
	uint32 indexL = 0;
	uint32 countL = 0;

	if( ptrA->sharedE ) return 0;

	while( indexL < ptrA->allocIndexE )
	{
		uint32 sizeL = *( uint32* )( ptrA->memPtrE + indexL );
		indexL += ( sizeL & 0xFFFFFFFE );
		countL += ( ( sizeL & 1 ) == 0 );
	}
	return countL;
}

/* ------------------------------------------------------------------------- */

/* ========================================================================= */
/*                                                                           */
/* ---- \ghd{ modify functions } ------------------------------------------- */
/*                                                                           */
/* ========================================================================= */

/* ------------------------------------------------------------------------- */

/* ========================================================================= */
/*                                                                           */
/* ---- \ghd{ I/O } -------------------------------------------------------- */
/*                                                                           */
/* ========================================================================= */

/* ------------------------------------------------------------------------- */

/* ========================================================================= */
/*                                                                           */
/* ---- \ghd{ exec functions } --------------------------------------------- */
/*                                                                           */
/* ========================================================================= */

/* ------------------------------------------------------------------------- */

struct bbs_MemSeg bbs_MemSeg_create( struct bbs_Context* cpA,
									 void* memPtrA, uint32 sizeA )
{
	struct bbs_MemSeg memSegL;
	memSegL.memPtrE     = ( uint16* )memPtrA;
	memSegL.sizeE       = sizeA & 0xFFFFFFFE; /* enforce even size to avoid overflow problems */
	memSegL.allocIndexE = 0;
	memSegL.sharedE     = FALSE;
	memSegL.idE         = 0;
	memSegL.dynMemManagerPtrE = NULL;
	return memSegL;
}

/* ------------------------------------------------------------------------- */

struct bbs_MemSeg bbs_MemSeg_createShared( struct bbs_Context* cpA,
										   void* memPtrA, uint32 sizeA )
{
	struct bbs_MemSeg memSegL;
	memSegL.memPtrE     = ( uint16* )memPtrA;
	memSegL.sizeE       = sizeA;
	memSegL.allocIndexE = 0;
	memSegL.sharedE     = TRUE;
	memSegL.idE         = 0;
	memSegL.dynMemManagerPtrE = NULL;
	return memSegL;
}

/* ------------------------------------------------------------------------- */

void* bbs_MemSeg_alloc( struct bbs_Context* cpA, 
					    struct bbs_MemSeg* ptrA, 
						uint32 sizeA )
{
	uint16* memPtrL = NULL;

	if( bbs_Context_error( cpA ) ) return NULL;

	if( !ptrA->sharedE )
	{
		if( ptrA->dynMemManagerPtrE == NULL )
		{
			uint32 effSizeL = sizeA + ( sizeA & 1 ) + 2; /* effective block size */
			memPtrL = ptrA->memPtrE + ptrA->allocIndexE;
			*( ( uint32* )memPtrL ) = effSizeL;
			memPtrL += 2;
			if( ptrA->allocIndexE + effSizeL > ptrA->sizeE )
			{
				bbs_ERR2( bbs_ERR_MEMORY_OVERFLOW,
						  "uint16* bbs_MemSeg_alloc( struct bbs_MemSeg* ptrA, uint32 sizeA ):\n"
						  "Exclusive Memory overflow. Segment size: %i. Requested size: %i", ptrA->sizeE, sizeA );
				return NULL;
			}
			ptrA->allocIndexE += effSizeL;
		}
		else
		{
			memPtrL = bbs_DynMemManager_alloc( cpA, ptrA->dynMemManagerPtrE, ptrA, sizeA );
		}
	}
	else
	{
		uint32 effSizeL = sizeA + ( sizeA & 1 );  /* effective block size */

		if( ptrA->allocIndexE + effSizeL > ptrA->sizeE  + ( ptrA->sizeE & 1 ) )
		{
			if( ptrA->dynMemManagerPtrE == NULL )
			{
				bbs_ERR2( bbs_ERR_MEMORY_OVERFLOW,
						  "uint16* bbs_MemSeg_alloc( struct bbs_MemSeg* ptrA, uint32 sizeA ):\n"
						  "Shared Memory overflow. Segment size: %i. Requested size: %i", ptrA->sizeE, sizeA );
				return NULL;
			}
			else
			{
				uint32 actualBlockSizeL = 0;
				ptrA->memPtrE = bbs_DynMemManager_nextBlock( cpA, ptrA->dynMemManagerPtrE, ptrA, ptrA->memPtrE, effSizeL, &actualBlockSizeL );
				ptrA->sizeE = actualBlockSizeL;
				ptrA->allocIndexE = 0;
			}
		}

		memPtrL = ptrA->memPtrE + ptrA->allocIndexE;
		ptrA->allocIndexE += effSizeL;
	}

	#if defined( HW_TMS320C5x )
	#ifdef DEBUG2
	{
		/* check if segment crosses page boundary */
		if( ( ( ( uint32 ) ptrA->memPtrE ) >> 16 ) !=
			( ( ( uint32 ) ptrA->memPtrE + ( ptrA->sizeE - 1 ) ) >> 16 ) )
		{
			bbs_ERROR0( "uint16* bbs_MemSeg_alloc( struct bbs_MemSeg* ptrA, uint32 sizeA ):\nSegment crosses page boundary\n" );
			return NULL;
		}
	}
	#endif
	#endif

	return memPtrL;
}

/* ------------------------------------------------------------------------- */

void bbs_MemSeg_free( struct bbs_Context* cpA,
					  struct bbs_MemSeg* ptrA,
					  void* memPtrA )
{
	bbs_DEF_fNameL( "void bbs_MemSeg_free( struct bbs_MemSeg* ptrA, void* memPtrA )" )

	if( bbs_Context_error( cpA ) ) return;

	/** only valid exclusive segments can be freed */
	if( ptrA == NULL || memPtrA == NULL || ptrA->sharedE ) return;

	if( ptrA->dynMemManagerPtrE != NULL )
	{
		bbs_DynMemManager_free( cpA, ptrA->dynMemManagerPtrE, memPtrA );
	}
	else
	{
		uint32 indexL, sizeL;
		uint16* memPtrL;

		if( ptrA == NULL || memPtrA == NULL ) return;
		if( ptrA->sharedE ) return;

		#ifdef HW_TMS320C5x
			indexL = ( uint32 ) memPtrA - ( uint32 ) ptrA->memPtrE - 2;
		#else
			indexL = ( uint16* )memPtrA - ptrA->memPtrE - 2;
		#endif

		memPtrL = ptrA->memPtrE + indexL;
		sizeL = *( ( int32* )memPtrL );

		/* checks */
		if( indexL > ptrA->allocIndexE || ( indexL & 1 ) != 0 )
		{
			bbs_ERROR4( "%s\n: Invalid memory.\n"
						"sizeE       = %i\n"
						"allocIndexE = %i\n"
						"indexL      = %i\n",
						fNameL,
						ptrA->sizeE,
						ptrA->allocIndexE,
						indexL );
			return;
		}

		if( ( sizeL & 1 ) != 0 )
		{
			bbs_ERROR1( "%s\n: Memory block was already freed once", fNameL );
			return;
		}

		*( ( uint32* )memPtrL ) += 1; /* odd size value indicates unused memory block */

		/* free last unused blocks if any */
		if( indexL + sizeL == ptrA->allocIndexE )
		{
			uint32 newAllocIndexL = 0;
			indexL = 0;
			while( indexL < ptrA->allocIndexE )
			{
				uint32 sizeL = *( uint32* )( ptrA->memPtrE + indexL );
				indexL += ( sizeL & 0xFFFFFFFE );
				if( ( sizeL & 1 ) == 0 )
				{
					newAllocIndexL = indexL;
				}
			}

			ptrA->allocIndexE = newAllocIndexL;
		}

	#ifdef DEBUG2
		bbs_MemSeg_checkConsistency( cpA, ptrA );
	#endif

	}
}

/* ------------------------------------------------------------------------- */

void bbs_MemSeg_checkConsistency( struct bbs_Context* cpA,
								  const struct bbs_MemSeg* ptrA )
{
	uint32 indexL = 0;

	if( ptrA->sharedE ) return;

	while( indexL < ptrA->allocIndexE )
	{
		uint32 sizeL = *( uint32* )( ptrA->memPtrE + indexL );
		indexL += ( sizeL & 0xFFFFFFFE );
	}

	if( indexL != ptrA->allocIndexE )
	{
		bbs_ERROR0( "Memory consistency check failed" );
	}
}

/* ------------------------------------------------------------------------- */

/* ========================================================================= */