| /* |
| * 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/Functions.h" |
| #include "b_BasicEm/DynMemManager.h" |
| #include "b_BasicEm/Context.h" |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* minimum block size dynamically allocated in function nextBlock (affects only shared memory) */ |
| #define bbs_DYN_MEM_MIN_NEW_BLOCK_SIZE 0 |
| |
| /** Offset to actual memory area on allocated memory blocks (in 16-bit words). |
| * Value needs to be large enough to hold the pointer to the next memory block |
| * and the size value (32-bit) of the memory area. |
| */ |
| #define bbs_MEM_OFFSET 6 |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ auxiliary functions } ---------------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ constructor / destructor } ----------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bbs_DynMemManager_init( struct bbs_Context* cpA, |
| struct bbs_DynMemManager* ptrA ) |
| { |
| ptrA->memPtrE = NULL; |
| ptrA->mallocFPtrE = NULL; |
| ptrA->freeFPtrE = NULL; |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bbs_DynMemManager_exit( struct bbs_Context* cpA, |
| struct bbs_DynMemManager* ptrA ) |
| { |
| ptrA->memPtrE = NULL; |
| ptrA->mallocFPtrE = NULL; |
| ptrA->freeFPtrE = NULL; |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ operators } -------------------------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ query functions } -------------------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| uint32 bbs_DynMemManager_allocatedSize( struct bbs_Context* cpA, |
| const struct bbs_DynMemManager* ptrA ) |
| { |
| uint32 sizeL = 0; |
| uint16* pL = ( uint16* )ptrA->memPtrE; |
| while( pL != NULL ) |
| { |
| sizeL += ( ( uint32* )pL )[ 2 ]; |
| pL = *( uint16** )pL; |
| } |
| return sizeL; |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ modify functions } ------------------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ I/O } -------------------------------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ exec functions } --------------------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| uint16* bbs_DynMemManager_alloc( struct bbs_Context* cpA, |
| struct bbs_DynMemManager* ptrA, |
| const struct bbs_MemSeg* memSegPtrA, |
| uint32 sizeA ) |
| { |
| uint16* pL = NULL; |
| bbs_DEF_fNameL( "uint16* bbs_DynMemManager_alloc( struct bbs_DynMemManager* ptrA, uint32 sizeA )" ) |
| |
| |
| if( ptrA->mallocFPtrE == NULL ) |
| { |
| bbs_ERROR1( "%s:\n Malloc handler not defined.\n", fNameL ); |
| return NULL; |
| } |
| |
| if( ptrA->memPtrE == NULL ) |
| { |
| ptrA->memPtrE = ptrA->mallocFPtrE( cpA, memSegPtrA, ( sizeA + bbs_MEM_OFFSET ) << 1 ); |
| pL = ptrA->memPtrE; |
| } |
| else |
| { |
| uint16** ppL = ( uint16** )ptrA->memPtrE; |
| while( *ppL != NULL ) ppL = ( uint16** )*ppL; |
| *ppL = ptrA->mallocFPtrE( cpA, memSegPtrA, ( sizeA + bbs_MEM_OFFSET ) << 1 ); |
| pL = *ppL; |
| } |
| |
| if( pL == NULL ) |
| { |
| bbs_ERR1( bbs_ERR_OUT_OF_MEMORY, "%s:\n Allocation failed.\n", fNameL ); |
| return NULL; |
| } |
| |
| ( ( uint32* )pL )[ 0 ] = 0; |
| ( ( uint32* )pL )[ 1 ] = 0; |
| ( ( uint32* )pL )[ 2 ] = sizeA + bbs_MEM_OFFSET; |
| |
| return pL + bbs_MEM_OFFSET; |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bbs_DynMemManager_free( struct bbs_Context* cpA, |
| struct bbs_DynMemManager* ptrA, |
| uint16* memPtrA ) |
| { |
| bbs_DEF_fNameL( "void bbs_DynMemManager_free( .... )" ) |
| |
| if( ptrA->memPtrE == NULL ) |
| { |
| bbs_ERROR1( "%s:\n Memory was not allocated.\n", fNameL ); |
| return; |
| } |
| else if( ptrA->memPtrE + bbs_MEM_OFFSET == memPtrA ) |
| { |
| uint16* memPtrL = ptrA->memPtrE; |
| ptrA->memPtrE = *( uint16** )ptrA->memPtrE; |
| ptrA->freeFPtrE( memPtrL ); |
| } |
| else |
| { |
| uint16* p0L = NULL; |
| uint16* pL = ( uint16* )ptrA->memPtrE; |
| |
| while( pL != NULL ) |
| { |
| if( pL + bbs_MEM_OFFSET == memPtrA ) break; |
| p0L = pL; |
| pL = *( uint16** )pL; |
| } |
| |
| if( pL != NULL ) |
| { |
| if( ptrA->freeFPtrE == NULL ) |
| { |
| bbs_ERROR1( "%s:\n Free handler not defined.\n", fNameL ); |
| return; |
| } |
| |
| if( p0L != NULL ) |
| { |
| *( uint16** )p0L = *( uint16** )pL; |
| } |
| else |
| { |
| ptrA->memPtrE = *( uint16** )pL; |
| } |
| |
| ptrA->freeFPtrE( pL ); |
| } |
| else |
| { |
| bbs_ERROR1( "%s:\n Attempt to free memory that was not allocated.\n", fNameL ); |
| return; |
| } |
| } |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| uint16* bbs_DynMemManager_nextBlock( struct bbs_Context* cpA, |
| struct bbs_DynMemManager* ptrA, |
| const struct bbs_MemSeg* memSegPtrA, |
| uint16* curBlockPtrA, |
| uint32 minSizeA, |
| uint32* actualSizePtrA ) |
| { |
| uint16* pL = ( uint16* )ptrA->memPtrE; |
| bbs_DEF_fNameL( "uint16* bbs_DynMemManager_nextBlock( .... )" ) |
| |
| if( curBlockPtrA != NULL ) |
| { |
| /* find current block */ |
| while( pL != NULL ) |
| { |
| if( pL + bbs_MEM_OFFSET == curBlockPtrA ) break; |
| pL = *( uint16** )pL; |
| } |
| |
| if( pL == NULL ) |
| { |
| bbs_ERROR1( "%s:\nCould not find current memory block.\n", fNameL ); |
| *actualSizePtrA = 0; |
| return NULL; |
| } |
| |
| /* go to next block */ |
| pL = *( uint16** )pL; |
| } |
| |
| /* find next fitting block */ |
| while( pL != NULL ) |
| { |
| if( ( ( uint32* )pL )[ 2 ] >= minSizeA + bbs_MEM_OFFSET ) break; |
| pL = *( uint16** )pL; |
| } |
| |
| if( pL == NULL ) |
| { |
| /* no proper block -> allocate new one */ |
| uint32 blockSizeL = minSizeA > bbs_DYN_MEM_MIN_NEW_BLOCK_SIZE ? minSizeA : bbs_DYN_MEM_MIN_NEW_BLOCK_SIZE; |
| uint16* memPtrL = bbs_DynMemManager_alloc( cpA, ptrA, memSegPtrA, blockSizeL ); |
| if( memPtrL != NULL ) |
| { |
| *actualSizePtrA = blockSizeL; |
| } |
| else |
| { |
| *actualSizePtrA = 0; |
| } |
| return memPtrL; |
| } |
| else |
| { |
| *actualSizePtrA = ( ( uint32* )pL )[ 2 ] - bbs_MEM_OFFSET; |
| return pL + bbs_MEM_OFFSET; |
| } |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bbs_DynMemManager_freeAll( struct bbs_Context* cpA, struct bbs_DynMemManager* ptrA ) |
| { |
| uint16** ppL = ( uint16** )ptrA->memPtrE; |
| while( ppL != NULL ) |
| { |
| uint16* memPtrL = ( uint16* )ppL; |
| ppL = ( uint16** )*ppL; |
| ptrA->freeFPtrE( memPtrL ); |
| } |
| ptrA->memPtrE = NULL; |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |