/* * 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/Context.h" #include "b_BasicEm/MemTbl.h" #include "b_BasicEm/Functions.h" /* ------------------------------------------------------------------------- */ /* ========================================================================= */ /* */ /* ---- \ghd{ auxiliary functions } ---------------------------------------- */ /* */ /* ========================================================================= */ /* ------------------------------------------------------------------------- */ flag bbs_MemTbl_memOverlap( const uint16* memPtr1A, uint32 size1A, const uint16* memPtr2A, uint32 size2A ) { int32 diffL = memPtr2A - memPtr1A; if( diffL >= 0 && diffL < ( int32 )size1A ) return TRUE; diffL += ( int32 )size2A; if( diffL >= 0 && diffL < ( int32 )size1A ) return TRUE; return FALSE; } /* ------------------------------------------------------------------------- */ /* ========================================================================= */ /* */ /* ---- \ghd{ constructor / destructor } ----------------------------------- */ /* */ /* ========================================================================= */ /* ------------------------------------------------------------------------- */ void bbs_MemTbl_init( struct bbs_Context* cpA, struct bbs_MemTbl* ptrA ) { uint32 iL; for( iL = 0; iL < bbs_MAX_MEM_SEGS; iL++ ) { bbs_MemSeg_init( cpA, &ptrA->esArrE[ iL ] ); bbs_MemSeg_init( cpA, &ptrA->ssArrE[ iL ] ); ptrA->espArrE[ iL ] = NULL; } ptrA->esSizeE = 0; ptrA->ssSizeE = 0; } /* ------------------------------------------------------------------------- */ void bbs_MemTbl_exit( struct bbs_Context* cpA, struct bbs_MemTbl* ptrA ) { uint32 iL; for( iL = 0; iL < bbs_MAX_MEM_SEGS; iL++ ) { bbs_MemSeg_exit( cpA, &ptrA->esArrE[ iL ] ); bbs_MemSeg_exit( cpA, &ptrA->ssArrE[ iL ] ); ptrA->espArrE[ iL ] = NULL; } ptrA->esSizeE = 0; ptrA->ssSizeE = 0; } /* ------------------------------------------------------------------------- */ /* ========================================================================= */ /* */ /* ---- \ghd{ operators } -------------------------------------------------- */ /* */ /* ========================================================================= */ /* ------------------------------------------------------------------------- */ /* ========================================================================= */ /* */ /* ---- \ghd{ query functions } -------------------------------------------- */ /* */ /* ========================================================================= */ /* ------------------------------------------------------------------------- */ flag bbs_MemTbl_overlap( struct bbs_Context* cpA, struct bbs_MemTbl* ptrA, const void* memPtrA, uint32 sizeA ) { uint32 iL; for( iL = 0; iL < ptrA->esSizeE; iL++ ) { if( bbs_MemTbl_memOverlap( ptrA->espArrE[ iL ]->memPtrE, ptrA->espArrE[ iL ]->sizeE, memPtrA, sizeA ) ) { return TRUE; } } for( iL = 0; iL < ptrA->ssSizeE; iL++ ) { if( bbs_MemTbl_memOverlap( ptrA->ssArrE[ iL ].memPtrE, ptrA->ssArrE[ iL ].sizeE, memPtrA, sizeA ) ) { return TRUE; } } return FALSE; } /* ------------------------------------------------------------------------- */ /* ========================================================================= */ /* */ /* ---- \ghd{ modify functions } ------------------------------------------- */ /* */ /* ========================================================================= */ /* ------------------------------------------------------------------------- */ /* ========================================================================= */ /* */ /* ---- \ghd{ I/O } -------------------------------------------------------- */ /* */ /* ========================================================================= */ /* ------------------------------------------------------------------------- */ /* ========================================================================= */ /* */ /* ---- \ghd{ exec functions } --------------------------------------------- */ /* */ /* ========================================================================= */ /* ------------------------------------------------------------------------- */ void bbs_MemTbl_create( struct bbs_Context* cpA, struct bbs_MemTbl* ptrA, void* memPtrA, uint32 sizeA, uint32 sharedSubSizeA ) { if( sharedSubSizeA > sizeA ) { bbs_ERROR0( "struct bbs_MemTbl bbs_MemTbl_create( void* memPtrA, uint32 sizeA, uint32 sharedSubSizeA ):\n" "sharedSubSizeA > sizeA" ); return; } bbs_MemTbl_init( cpA, ptrA ); ptrA->esArrE[ 0 ] = bbs_MemSeg_create( cpA, memPtrA, sizeA - sharedSubSizeA ); #ifdef HW_TMS320C5x ptrA->ssArrE[ 0 ] = bbs_MemSeg_createShared( cpA, ( uint16* ) ( ( int32 ) ( ( uint16* )memPtrA ) + sizeA - sharedSubSizeA ), sharedSubSizeA ); #else ptrA->ssArrE[ 0 ] = bbs_MemSeg_createShared( cpA, ( uint16* )memPtrA + sizeA - sharedSubSizeA, sharedSubSizeA ); #endif ptrA->espArrE[ 0 ] = &ptrA->esArrE[ 0 ]; ptrA->esSizeE = 1; ptrA->ssSizeE = 1; } /* ------------------------------------------------------------------------- */ void bbs_MemTbl_add( struct bbs_Context* cpA, struct bbs_MemTbl* ptrA, void* memPtrA, uint32 sizeA, uint32 idA ) { if( ptrA->esSizeE == bbs_MAX_MEM_SEGS ) { bbs_ERROR0( "void bbs_MemTbl_add( struct bbs_MemTbl* ptrA, void* memPtrA, uint32 sizeA ):\n" "Table is full! Increase constant bbs_MAX_MEM_SEGS" ); return; } ptrA->esArrE[ ptrA->esSizeE ] = bbs_MemSeg_create( cpA, memPtrA, sizeA ); ptrA->esArrE[ ptrA->esSizeE ].idE = idA; ptrA->espArrE[ ptrA->esSizeE ] = &ptrA->esArrE[ ptrA->esSizeE ]; ptrA->esSizeE++; } /* ------------------------------------------------------------------------- */ void bbs_MemTbl_addShared( struct bbs_Context* cpA, struct bbs_MemTbl* ptrA, void* memPtrA, uint32 sizeA, uint32 idA ) { if( ptrA->ssSizeE == bbs_MAX_MEM_SEGS ) { bbs_ERROR0( "void bbs_MemTbl_addShared( struct bbs_MemTbl* ptrA, void* memPtrA, uint32 sizeA ):\n" "Table is full! Increase constant bbs_MAX_MEM_SEGS" ); return; } ptrA->ssArrE[ ptrA->ssSizeE ] = bbs_MemSeg_createShared( cpA, memPtrA, sizeA ); ptrA->ssArrE[ ptrA->ssSizeE ].idE = idA; ptrA->ssSizeE++; } /* ------------------------------------------------------------------------- */ struct bbs_MemSeg* bbs_MemTbl_segPtr( struct bbs_Context* cpA, struct bbs_MemTbl* ptrA, uint32 idA ) { uint32 iL; if( ptrA->esSizeE == 0 ) { bbs_ERROR0( "bbs_MemTbl_segPtr(): Table contains no exclusive segments." ); return NULL; } if( idA > 0 ) { for( iL = 0; iL < ptrA->esSizeE; iL++ ) { if( idA == ptrA->espArrE[ iL ]->idE ) return ptrA->espArrE[ iL ]; } } for( iL = 0; iL < ptrA->esSizeE; iL++ ) { if( ptrA->espArrE[ iL ]->sizeE > 0 || ptrA->espArrE[ iL ]->dynMemManagerPtrE != 0 ) { return ptrA->espArrE[ iL ]; } } bbs_ERR0( bbs_ERR_MEMORY_OVERFLOW, "bbs_MemTbl_segPtr(): Table contains no valid exclusive segments." ); return 0; } /* ------------------------------------------------------------------------- */ struct bbs_MemSeg* bbs_MemTbl_sharedSegPtr( struct bbs_Context* cpA, struct bbs_MemTbl* ptrA, uint32 idA ) { uint32 iL; if( ptrA->ssSizeE == 0 ) { bbs_ERROR0( "bbs_MemTbl_sharedSegPtr(): Table contains no shared segments." ); return NULL; } if( idA > 0 ) { for( iL = 0; iL < ptrA->ssSizeE; iL++ ) { if( idA == ptrA->ssArrE[ iL ].idE ) return &ptrA->ssArrE[ iL ]; } } for( iL = 0; iL < ptrA->ssSizeE; iL++ ) { if( ptrA->ssArrE[ iL ].sizeE > 0 || ptrA->ssArrE[ iL ].dynMemManagerPtrE != 0 ) { return &ptrA->ssArrE[ iL ]; } } bbs_ERR0( bbs_ERR_MEMORY_OVERFLOW, "bbs_MemTbl_sharedSegPtr(): Table contains no valid shared segments." ); return 0; } /* ------------------------------------------------------------------------- */ struct bbs_MemSeg* bbs_MemTbl_fastestSegPtr( struct bbs_Context* cpA, struct bbs_MemTbl* ptrA, uint32 minSizeA ) { uint32 iL; for( iL = 0; iL < ptrA->esSizeE; iL++ ) { if( bbs_MemSeg_availableSize( cpA, ptrA->espArrE[ iL ] ) >= minSizeA ) break; } if( iL == ptrA->esSizeE ) { if( ptrA->esSizeE == 0 ) { bbs_ERROR0( "struct bbs_MemSeg* bbs_MemTbl_fastestSegPtr( struct bbs_MemTbl* ptrA, uint32 minSizeA ):\n" "Table contains no exclusive segments" ); return NULL; } else { bbs_ERR0( bbs_ERR_MEMORY_OVERFLOW, "struct bbs_MemSeg* bbs_MemTbl_fastestSegPtr( struct bbs_MemTbl* ptrA, uint32 minSizeA ):\n" "Could not find segment with sufficient free space" ); return NULL; } } if( ptrA->espArrE[ iL ]->sharedE ) { bbs_ERROR0( "struct bbs_MemSeg* bbs_MemTbl_fastestSegPtr( struct bbs_MemTbl* ptrA, uint32 minSizeA ):\n" "Table corrupt: Found shared segment in exclusive table" ); return NULL; } return ptrA->espArrE[ iL ]; } /* ------------------------------------------------------------------------- */ struct bbs_MemSeg* bbs_MemTbl_largestSegPtr( struct bbs_Context* cpA, struct bbs_MemTbl* ptrA ) { uint32 iL; uint32 maxIndexL = 0; uint32 maxSizeL = 0; if( ptrA->esSizeE == 0 ) { bbs_ERROR0( "struct bbs_MemSeg* bbs_MemTbl_largestSegPtr( struct bbs_MemTbl* ptrA ):\n" "No exclusive segments available" ); return NULL; } for( iL = 0; iL < ptrA->esSizeE; iL++ ) { uint32 sizeL = bbs_MemSeg_availableSize( cpA, ptrA->espArrE[ iL ] ); if( sizeL > maxSizeL ) { maxSizeL = sizeL; maxIndexL = iL; } } if( ptrA->espArrE[ maxIndexL ]->sharedE ) { bbs_ERROR0( "struct bbs_MemSeg* bbs_MemTbl_largestSegPtr( struct bbs_MemTbl* ptrA ):\n" "Table corrupt: Found shared segment in exclusive table" ); return NULL; } return ptrA->espArrE[ maxIndexL ]; } /* ------------------------------------------------------------------------- */ struct bbs_MemSeg* bbs_MemTbl_fastestSharedSegPtr( struct bbs_Context* cpA, struct bbs_MemTbl* ptrA, uint32 minSizeA ) { uint32 iL; for( iL = 0; iL < ptrA->ssSizeE; iL++ ) { if( bbs_MemSeg_availableSize( cpA, &ptrA->ssArrE[ iL ] ) >= minSizeA ) break; } if( iL == ptrA->ssSizeE ) { if( ptrA->esSizeE == 0 ) { bbs_ERROR0( "struct bbs_MemSeg* bbs_MemTbl_fastestSegPtr( struct bbs_MemTbl* ptrA, uint32 minSizeA ):\n" "Table contains no shared segments" ); return NULL; } else { bbs_ERR0( bbs_ERR_MEMORY_OVERFLOW, "struct bbs_MemSeg* bbs_MemTbl_fastestSharedSegPtr( struct bbs_MemTbl* ptrA, uint32 minSizeA ):\n" "Could not find segment with sufficient free space" ); return NULL; } } if( !ptrA->ssArrE[ iL ].sharedE ) { bbs_ERROR0( "struct bbs_MemSeg* bbs_MemTbl_fastestSharedSegPtr( struct bbs_MemTbl* ptrA, uint32 minSizeA ):\n" "Table corrupt: Found exclusive segment in shared table" ); return NULL; } return &ptrA->ssArrE[ iL ]; } /* ------------------------------------------------------------------------- */ struct bbs_MemSeg* bbs_MemTbl_largestSharedSegPtr( struct bbs_Context* cpA, struct bbs_MemTbl* ptrA ) { uint32 iL; uint32 maxIndexL = 0; uint32 maxSizeL = 0; if( ptrA->ssSizeE == 0 ) { bbs_ERROR0( "struct bbs_MemSeg* bbs_MemTbl_largestSharedSegPtr( struct bbs_MemTbl* ptrA ):\n" "No shared segments available" ); return NULL; } for( iL = 0; iL < ptrA->ssSizeE; iL++ ) { uint32 sizeL = bbs_MemSeg_availableSize( cpA, &ptrA->ssArrE[ iL ] ); if( sizeL > maxSizeL ) { maxSizeL = sizeL; maxIndexL = iL; } } if( !ptrA->ssArrE[ maxIndexL ].sharedE ) { bbs_ERROR0( "struct bbs_MemSeg* bbs_MemTbl_largestSharedSegPtr( struct bbs_MemTbl* ptrA ):\n" "Table corrupt: Found exclusive segment in shared table" ); return NULL; } return &ptrA->ssArrE[ maxIndexL ]; } /* ------------------------------------------------------------------------- */ /* ========================================================================= */