Dynamic loading in embedded sytem

来源:互联网 发布:刺客信条2优化怎么样 编辑:程序博客网 时间:2024/05/22 13:40

        参考代码来源于《嵌入式系统开发之道》P378-381,对其中的注释进行了修改。另外,需要指出的是,源代码中对control table和相应的存储block的申请和释放,考虑了要和相邻块尽可能的进行合并,这样可以减少碎片。

 #define TBL_WIDTH 8 /* the occupied byte numbers in a item of the control Table */


unsigned char *ansi_ucStartAlloc; /* allocate area, start address */
unsigned char *ansi_ucEndAlloc; /* allocate area, end address*/
unsigned char *ansi_ucNxtAlcP; /* next allocate address*/
unsigned char *ansi_ucTblPtr; /* next address for table*/
unsigned long  ansi_ulRow; /* table count*/


/* Control Table */
typedef struct {
unsigned long ulAddrTbl;
unsigned long ulSizeTbl;
} sTable;


/* calculate pointer and size consider boundary size */
#define _BOUND(siz) ((siz + _BOUNDARY - 1) & (~(_BOUNDARY-1)))


/* shift the item to high address by one unit */
extern void ANSI_SFTR1ROW(unsigned long address, unsigned long count);


/* function : ansi_InitMalloc() */
int ansi_InitMalloc( unsigned long ulStartAlloc, unsigned long count )
{
/* allocate start address, 4 bytes boundary */
ansi_ucStartAlloc= (unsigned char *)((ulStartAlloc +3) & 0xfffffffc);


/* allocate end address, 4 bytes boundary */
ansi_ucEndAlloc= (unsigned char *)((ulEndAlloc + 3) & 0xfffffffc);


if ( ansi_ucStartAlloc + TBL_WIDTH + 8 > ansi_ucEndAlloc)
{
return -1;
}


ansi_ucNxtAlcP= ansi_ucStartAlloc; /* next allocate address */
ansi_ucTblPtr = ansi_ucEndAlloc - TBL_WIDTH; /* the start address of the control table */
ansi_ulRow = 0;
return 0;
}


/* function: malloc */
void * malloc(size_t tdsiz)
{
sTable *stTblPtr;
unsigned long ulSizeWk;
unsigned long ulAddrWk;
unsigned long ulTemp;
unsigned long ulAddrTmp;
int iErrors = 0;
int iCount;
int iRow;


if (tdsiz == 0)
{
return (void*)NULL;
}


/* table start address, now point to the last item */
stTblPtr = (sTable*)(ansi_ucEndAlloc - TBL_WIDTH);


/* the left space from the allocated memory to the control table is not enough for a TBL_WIDTH */
if(((ansi_ucTblPtr) - ansi_ucNxtAlcP ) < TBL_WIDTH)
{
errno = ENOMEM;
return (void*)NULL;
}


/* table check, top to bottom ----------------------------------*/
for ( iCount = 0; iCount < ansi_ulRow; iCount++, stTblPtr--)
{
ulTemp = stTblPtr->ulSizeTbl & 0x00000001;


// this block has not been used
if ( ulTemp == 0)
{
// this block is free area
if ( stTblPtr->ulSizeTbl >= _BOUND(tdSiz))
{
/* check memory space */
ulSizeWk = stTblPtr->ulSizeTbl - _BOUND(tdSiz);
/* reset memory size, and set the used flag to this allocated block */
stTblPtr->ulSizeTbl = _BOUND(tdSiz) | 0x1;


ulAddrWk = stTblPtr->ulAddrTbl; /* allocated address */


/* rest data size is not zero, and in fact it adds a new block  */
if ( ulSizeWk > 0 )
{
ulAddrTmp = (unsigned long)(ansi_ucTblPtr);
iRow = ansi_ulRow - iCount - 1;


/* shift table data */
ANSI_SFTR1ROW( ulAddrTmp, iRow );


stTblPtr--;
stTblPtr->ulSizeTbl= ulSizeWk; /* entry, rest size */
stTblPtr->ulAddrTbl= ulAddrWk + _BOUND(tdsiz);
ansi_ucTblPtr -= TBL_WIDTH;
ansi_ulRow++;
}


return (void*)ulAddrWk;/* normal end */
}
/* memory space are insufficient, continue next row line */
}
/* not memory space, continue next row line */
}


/* the left space is not enough for a required block */
if ((ansi_ucTblPtr - ansi_ucNxtAlcP) < (_BOUND(tdsiz)+TBL_WIDTH))
{
errno = ENOMEM;
return (void*)NULL;/* can not allocate memory */
}
else
{
/* entry, new row line */
ulAddrWk = (unsigned long)ansi_ucNxtAlcP; /* allocated top address */
stTblPtr->ulAddrTbl= ulAddrWk; /* store the top addr to the control table */
stTblPtr->ulSizeTbl= _BOUND(tdsiz)| 0X1; /* store the size of the allocated block and set the used flag */


ansi_ucNxtAlcP= ansi_ucNxtAlcP + _BOUND(tdsiz); /* update the next block addr, which is free to be allocated */
ansi_ulRow++;
ansi_ucTblPtr -= TBL_WIDTH; /* next item pointer in the control table */
return (void*)ulAddrWk;
}
}


/* transfer the item to the high address by one */
void ANSI_SFTR1ROW( unsigned long address, unsigned long count )
{
int i;
unsigned long *entry = (unsigned long *)address;
unsigned long *next_entry = (unsigned long *)(address+8);


for ( i = 0; i < count ; i++ )
{
entry[i*2] = next_entry[i*2]; /* move the address of the item */
entry[i*2 + 1] = next_entry[i*2 + 1]; /* move the size of the item */
}
}


/* function : free the memory and update the control table */
void free(void *vpFrePtrP)
{
sTable *sTblPtrFre;
unsigned long ulAddrWk;
unsigned long ulSizeWk;
unsigned long ulSizeWk2;
int iLoop;
int iRowCnt;
 
if (vpFrePtrP == NULL)
{
return;
}


/* point to the last item of the control table */
sTblPtrFre = (void*)(ansi_ucEndAlloc - TBL_WIDTH);


/* search in the contol table and free the specified block */
for ( iLoop = 0 ; iLoop < ansi_ulRow; iLoop++, sTblPtrFre--)
{
/* found block to free */
if ( vpFrePtrP == ( sTblPtrFre->ulAddrTbl  )
{
ulSizeWk = sTblPtrFre->ulSizeTbl & 0xfffffffe;
sTblPtrFre->ulSizeTbl= ulSizeWk; /* clear the flag and store the size */


/* the last data? */ 
if ( iLoop == ansi_ulRow - 1 )
{
ansi_ulRow--;
ansi_ucTblPtr += TBL_WIDTH;
ansi_ucNxtAlcP-= ulSizeWk;


sTblPtrFre += 1;


/* combine the neighbour free block to a new larger block */
if (( ansi_ulRow != 0 ) && (sTblPtrFre->ulSizeTbl & 0x1) == 0 )
{
ulSizeWk2 = sTblPtrFre->ulSizeTbl;


/* store the size */
sTblPtrFre->ulSizeTbl= ulSizeWk + ulSizeWk2;
ansi_ulRow--;
ansi_ucTblPtr += TBL_WIDTH;
ansi_ucNxtAlcP -= ulSizeWk2;
}
}
else
{
/* check if the previous block is free and can be merged and shift */
if (( iLoop != 0 ) && (( sTblPtrFre + 1 )->ulSizeTbl & 0x1 ) == 0 )
{
ulAddrWk = (unsigned long)sTblPtrFre;
sTblPtrFre++;
ulSizeWk = ulSizeWk + (sTblPtrFre->ulSizeTbl);


iRowCnt = ansi_ulRow - iLoop - 1;
ANSI_SFTF1ROW(ulAddrWk, iRowCnt);/* shift, table data */
ansi_ulRow--;
ansi_ucTblPtr += TBL_WIDTH;


iLoop--;
}


/* not the first item or the last one, and the next item is free block */
if ((iLoop < ansi_ulRow) && ((sTblPtrFre-1)->ulSizeTbl & 0x1) == 0 )
{
sTblPtrFre->ulSizeTbl= ulSizeWk + ((sTblPtrFre-1)->ulSizeTbl);


iLoop++;
sTblPtrFre--;
/* the number need to move */
iRowCnt = ansi_ulRow - iLoop - 1;
ulAddrWk = (unsigned long)sTblPtrFre;
ANSI_SFTF1ROW(ulAddrWk, iRowCnt);/* shift , table data */
ansi_ulRow--;
ansi_ucTblPtr += TBL_WIDTH;

}
}


return; /* normal end */
}
}


return; /* not found */
}       

原创粉丝点击