/* * 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" ); } } /* ------------------------------------------------------------------------- */ /* ========================================================================= */