Home | History | Annotate | Download | only in b_BasicEm
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /* ---- includes ----------------------------------------------------------- */
     18 
     19 #include "b_BasicEm/MemSeg.h"
     20 #include "b_BasicEm/Functions.h"
     21 #include "b_BasicEm/Context.h"
     22 
     23 /* ------------------------------------------------------------------------- */
     24 
     25 /* ========================================================================= */
     26 /*                                                                           */
     27 /* ---- \ghd{ auxiliary functions } ---------------------------------------- */
     28 /*                                                                           */
     29 /* ========================================================================= */
     30 
     31 /* ------------------------------------------------------------------------- */
     32 
     33 /* ========================================================================= */
     34 /*                                                                           */
     35 /* ---- \ghd{ constructor / destructor } ----------------------------------- */
     36 /*                                                                           */
     37 /* ========================================================================= */
     38 
     39 /* ------------------------------------------------------------------------- */
     40 
     41 void bbs_MemSeg_init( struct bbs_Context* cpA,
     42 					  struct bbs_MemSeg* ptrA )
     43 {
     44 	ptrA->memPtrE = NULL;
     45 	ptrA->sizeE = 0;
     46 	ptrA->allocIndexE = 0;
     47 	ptrA->sharedE = FALSE;
     48 	ptrA->idE = 0;
     49 	ptrA->dynMemManagerPtrE = NULL;
     50 }
     51 
     52 /* ------------------------------------------------------------------------- */
     53 
     54 void bbs_MemSeg_exit( struct bbs_Context* cpA,
     55 					  struct bbs_MemSeg* ptrA )
     56 {
     57 	ptrA->memPtrE = NULL;
     58 	ptrA->sizeE = 0;
     59 	ptrA->allocIndexE = 0;
     60 	ptrA->sharedE = FALSE;
     61 	ptrA->idE = 0;
     62 	ptrA->dynMemManagerPtrE = NULL;
     63 }
     64 
     65 /* ------------------------------------------------------------------------- */
     66 
     67 /* ========================================================================= */
     68 /*                                                                           */
     69 /* ---- \ghd{ operators } -------------------------------------------------- */
     70 /*                                                                           */
     71 /* ========================================================================= */
     72 
     73 /* ------------------------------------------------------------------------- */
     74 
     75 /* ========================================================================= */
     76 /*                                                                           */
     77 /* ---- \ghd{ query functions } -------------------------------------------- */
     78 /*                                                                           */
     79 /* ========================================================================= */
     80 
     81 /* ------------------------------------------------------------------------- */
     82 
     83 uint32 bbs_MemSeg_availableSize( struct bbs_Context* cpA,
     84 								 const struct bbs_MemSeg* ptrA )
     85 {
     86 	if( ptrA->dynMemManagerPtrE == NULL )
     87 	{
     88 		return ( ptrA->sizeE == ptrA->allocIndexE ) ? 0 : ptrA->sizeE - ptrA->allocIndexE - 2 * ptrA->sharedE;
     89 	}
     90 	else
     91 	{
     92 		return 0xFFFFFFFF;
     93 	}
     94 }
     95 
     96 /* ------------------------------------------------------------------------- */
     97 
     98 uint32 bbs_MemSeg_allocatedSize( struct bbs_Context* cpA,
     99 								 const struct bbs_MemSeg* ptrA )
    100 {
    101 	if( ptrA->dynMemManagerPtrE == NULL )
    102 	{
    103 		return ptrA->allocIndexE;
    104 	}
    105 	else
    106 	{
    107 		return bbs_DynMemManager_allocatedSize( cpA, ptrA->dynMemManagerPtrE );
    108 	}
    109 }
    110 
    111 /* ------------------------------------------------------------------------- */
    112 
    113 uint32 bbs_MemSeg_usedSize( struct bbs_Context* cpA,
    114 						    const struct bbs_MemSeg* ptrA )
    115 {
    116 	if( ptrA->dynMemManagerPtrE == NULL )
    117 	{
    118 		if( ptrA->sharedE )
    119 		{
    120 			return ptrA->allocIndexE;
    121 		}
    122 		else
    123 		{
    124 			uint32 indexL = 0;
    125 			uint32 countL = 0;
    126 			while( indexL < ptrA->allocIndexE )
    127 			{
    128 				uint32 sizeL = *( uint32* )( ptrA->memPtrE + indexL );
    129 				indexL += ( sizeL & 0xFFFFFFFE );
    130 				if( ( sizeL & 1 ) == 0 )
    131 				{
    132 					countL += sizeL - 2;
    133 				}
    134 			}
    135 			return countL;
    136 		}
    137 	}
    138 	else
    139 	{
    140 		return bbs_MemSeg_allocatedSize( cpA, ptrA );
    141 	}
    142 }
    143 
    144 /* ------------------------------------------------------------------------- */
    145 
    146 uint32 bbs_MemSeg_blocks( struct bbs_Context* cpA,
    147 						  const struct bbs_MemSeg* ptrA )
    148 {
    149 	uint32 indexL = 0;
    150 	uint32 countL = 0;
    151 
    152 	if( ptrA->sharedE ) return 0;
    153 
    154 	while( indexL < ptrA->allocIndexE )
    155 	{
    156 		uint32 sizeL = *( uint32* )( ptrA->memPtrE + indexL );
    157 		indexL += ( sizeL & 0xFFFFFFFE );
    158 		countL++;
    159 	}
    160 	return countL;
    161 }
    162 
    163 /* ------------------------------------------------------------------------- */
    164 
    165 uint32 bbs_MemSeg_usedBlocks( struct bbs_Context* cpA,
    166 							  const struct bbs_MemSeg* ptrA )
    167 {
    168 	uint32 indexL = 0;
    169 	uint32 countL = 0;
    170 
    171 	if( ptrA->sharedE ) return 0;
    172 
    173 	while( indexL < ptrA->allocIndexE )
    174 	{
    175 		uint32 sizeL = *( uint32* )( ptrA->memPtrE + indexL );
    176 		indexL += ( sizeL & 0xFFFFFFFE );
    177 		countL += ( ( sizeL & 1 ) == 0 );
    178 	}
    179 	return countL;
    180 }
    181 
    182 /* ------------------------------------------------------------------------- */
    183 
    184 /* ========================================================================= */
    185 /*                                                                           */
    186 /* ---- \ghd{ modify functions } ------------------------------------------- */
    187 /*                                                                           */
    188 /* ========================================================================= */
    189 
    190 /* ------------------------------------------------------------------------- */
    191 
    192 /* ========================================================================= */
    193 /*                                                                           */
    194 /* ---- \ghd{ I/O } -------------------------------------------------------- */
    195 /*                                                                           */
    196 /* ========================================================================= */
    197 
    198 /* ------------------------------------------------------------------------- */
    199 
    200 /* ========================================================================= */
    201 /*                                                                           */
    202 /* ---- \ghd{ exec functions } --------------------------------------------- */
    203 /*                                                                           */
    204 /* ========================================================================= */
    205 
    206 /* ------------------------------------------------------------------------- */
    207 
    208 struct bbs_MemSeg bbs_MemSeg_create( struct bbs_Context* cpA,
    209 									 void* memPtrA, uint32 sizeA )
    210 {
    211 	struct bbs_MemSeg memSegL;
    212 	memSegL.memPtrE     = ( uint16* )memPtrA;
    213 	memSegL.sizeE       = sizeA & 0xFFFFFFFE; /* enforce even size to avoid overflow problems */
    214 	memSegL.allocIndexE = 0;
    215 	memSegL.sharedE     = FALSE;
    216 	memSegL.idE         = 0;
    217 	memSegL.dynMemManagerPtrE = NULL;
    218 	return memSegL;
    219 }
    220 
    221 /* ------------------------------------------------------------------------- */
    222 
    223 struct bbs_MemSeg bbs_MemSeg_createShared( struct bbs_Context* cpA,
    224 										   void* memPtrA, uint32 sizeA )
    225 {
    226 	struct bbs_MemSeg memSegL;
    227 	memSegL.memPtrE     = ( uint16* )memPtrA;
    228 	memSegL.sizeE       = sizeA;
    229 	memSegL.allocIndexE = 0;
    230 	memSegL.sharedE     = TRUE;
    231 	memSegL.idE         = 0;
    232 	memSegL.dynMemManagerPtrE = NULL;
    233 	return memSegL;
    234 }
    235 
    236 /* ------------------------------------------------------------------------- */
    237 
    238 void* bbs_MemSeg_alloc( struct bbs_Context* cpA,
    239 					    struct bbs_MemSeg* ptrA,
    240 						uint32 sizeA )
    241 {
    242 	uint16* memPtrL = NULL;
    243 
    244 	if( bbs_Context_error( cpA ) ) return NULL;
    245 
    246 	if( !ptrA->sharedE )
    247 	{
    248 		if( ptrA->dynMemManagerPtrE == NULL )
    249 		{
    250 			uint32 effSizeL = sizeA + ( sizeA & 1 ) + 2; /* effective block size */
    251 			memPtrL = ptrA->memPtrE + ptrA->allocIndexE;
    252 			*( ( uint32* )memPtrL ) = effSizeL;
    253 			memPtrL += 2;
    254 			if( ptrA->allocIndexE + effSizeL > ptrA->sizeE )
    255 			{
    256 				bbs_ERR2( bbs_ERR_MEMORY_OVERFLOW,
    257 						  "uint16* bbs_MemSeg_alloc( struct bbs_MemSeg* ptrA, uint32 sizeA ):\n"
    258 						  "Exclusive Memory overflow. Segment size: %i. Requested size: %i", ptrA->sizeE, sizeA );
    259 				return NULL;
    260 			}
    261 			ptrA->allocIndexE += effSizeL;
    262 		}
    263 		else
    264 		{
    265 			memPtrL = bbs_DynMemManager_alloc( cpA, ptrA->dynMemManagerPtrE, ptrA, sizeA );
    266 		}
    267 	}
    268 	else
    269 	{
    270 		uint32 effSizeL = sizeA + ( sizeA & 1 );  /* effective block size */
    271 
    272 		if( ptrA->allocIndexE + effSizeL > ptrA->sizeE  + ( ptrA->sizeE & 1 ) )
    273 		{
    274 			if( ptrA->dynMemManagerPtrE == NULL )
    275 			{
    276 				bbs_ERR2( bbs_ERR_MEMORY_OVERFLOW,
    277 						  "uint16* bbs_MemSeg_alloc( struct bbs_MemSeg* ptrA, uint32 sizeA ):\n"
    278 						  "Shared Memory overflow. Segment size: %i. Requested size: %i", ptrA->sizeE, sizeA );
    279 				return NULL;
    280 			}
    281 			else
    282 			{
    283 				uint32 actualBlockSizeL = 0;
    284 				ptrA->memPtrE = bbs_DynMemManager_nextBlock( cpA, ptrA->dynMemManagerPtrE, ptrA, ptrA->memPtrE, effSizeL, &actualBlockSizeL );
    285 				ptrA->sizeE = actualBlockSizeL;
    286 				ptrA->allocIndexE = 0;
    287 			}
    288 		}
    289 
    290 		memPtrL = ptrA->memPtrE + ptrA->allocIndexE;
    291 		ptrA->allocIndexE += effSizeL;
    292 	}
    293 
    294 	#if defined( HW_TMS320C5x )
    295 	#ifdef DEBUG2
    296 	{
    297 		/* check if segment crosses page boundary */
    298 		if( ( ( ( uint32 ) ptrA->memPtrE ) >> 16 ) !=
    299 			( ( ( uint32 ) ptrA->memPtrE + ( ptrA->sizeE - 1 ) ) >> 16 ) )
    300 		{
    301 			bbs_ERROR0( "uint16* bbs_MemSeg_alloc( struct bbs_MemSeg* ptrA, uint32 sizeA ):\nSegment crosses page boundary\n" );
    302 			return NULL;
    303 		}
    304 	}
    305 	#endif
    306 	#endif
    307 
    308 	return memPtrL;
    309 }
    310 
    311 /* ------------------------------------------------------------------------- */
    312 
    313 void bbs_MemSeg_free( struct bbs_Context* cpA,
    314 					  struct bbs_MemSeg* ptrA,
    315 					  void* memPtrA )
    316 {
    317 	bbs_DEF_fNameL( "void bbs_MemSeg_free( struct bbs_MemSeg* ptrA, void* memPtrA )" )
    318 
    319 	if( bbs_Context_error( cpA ) ) return;
    320 
    321 	/** only valid exclusive segments can be freed */
    322 	if( ptrA == NULL || memPtrA == NULL || ptrA->sharedE ) return;
    323 
    324 	if( ptrA->dynMemManagerPtrE != NULL )
    325 	{
    326 		bbs_DynMemManager_free( cpA, ptrA->dynMemManagerPtrE, memPtrA );
    327 	}
    328 	else
    329 	{
    330 		uint32 indexL, sizeL;
    331 		uint16* memPtrL;
    332 
    333 		if( ptrA == NULL || memPtrA == NULL ) return;
    334 		if( ptrA->sharedE ) return;
    335 
    336 		#ifdef HW_TMS320C5x
    337 			indexL = ( uint32 ) memPtrA - ( uint32 ) ptrA->memPtrE - 2;
    338 		#else
    339 			indexL = ( uint16* )memPtrA - ptrA->memPtrE - 2;
    340 		#endif
    341 
    342 		memPtrL = ptrA->memPtrE + indexL;
    343 		sizeL = *( ( int32* )memPtrL );
    344 
    345 		/* checks */
    346 		if( indexL > ptrA->allocIndexE || ( indexL & 1 ) != 0 )
    347 		{
    348 			bbs_ERROR4( "%s\n: Invalid memory.\n"
    349 						"sizeE       = %i\n"
    350 						"allocIndexE = %i\n"
    351 						"indexL      = %i\n",
    352 						fNameL,
    353 						ptrA->sizeE,
    354 						ptrA->allocIndexE,
    355 						indexL );
    356 			return;
    357 		}
    358 
    359 		if( ( sizeL & 1 ) != 0 )
    360 		{
    361 			bbs_ERROR1( "%s\n: Memory block was already freed once", fNameL );
    362 			return;
    363 		}
    364 
    365 		*( ( uint32* )memPtrL ) += 1; /* odd size value indicates unused memory block */
    366 
    367 		/* free last unused blocks if any */
    368 		if( indexL + sizeL == ptrA->allocIndexE )
    369 		{
    370 			uint32 newAllocIndexL = 0;
    371 			indexL = 0;
    372 			while( indexL < ptrA->allocIndexE )
    373 			{
    374 				uint32 sizeL = *( uint32* )( ptrA->memPtrE + indexL );
    375 				indexL += ( sizeL & 0xFFFFFFFE );
    376 				if( ( sizeL & 1 ) == 0 )
    377 				{
    378 					newAllocIndexL = indexL;
    379 				}
    380 			}
    381 
    382 			ptrA->allocIndexE = newAllocIndexL;
    383 		}
    384 
    385 	#ifdef DEBUG2
    386 		bbs_MemSeg_checkConsistency( cpA, ptrA );
    387 	#endif
    388 
    389 	}
    390 }
    391 
    392 /* ------------------------------------------------------------------------- */
    393 
    394 void bbs_MemSeg_checkConsistency( struct bbs_Context* cpA,
    395 								  const struct bbs_MemSeg* ptrA )
    396 {
    397 	uint32 indexL = 0;
    398 
    399 	if( ptrA->sharedE ) return;
    400 
    401 	while( indexL < ptrA->allocIndexE )
    402 	{
    403 		uint32 sizeL = *( uint32* )( ptrA->memPtrE + indexL );
    404 		indexL += ( sizeL & 0xFFFFFFFE );
    405 	}
    406 
    407 	if( indexL != ptrA->allocIndexE )
    408 	{
    409 		bbs_ERROR0( "Memory consistency check failed" );
    410 	}
    411 }
    412 
    413 /* ------------------------------------------------------------------------- */
    414 
    415 /* ========================================================================= */
    416