📄 vm1_kmalloc.c
字号:
/***************************************************************************
** File name : vm1_kmalloc.c
** Author : x.cheng
** Create date :
**
** Comment:
** virtual memory manage module - kernel space malloc function
**
** Revisions:
** $Log: vm1_kmalloc.c,v $
** Revision 1.4 2005/08/05 15:13:25 x.cheng
** heap info display function upgrade...
**
** Revision 1.3 2005/08/02 15:39:35 x.cheng
** new debug function Vm1KeDumpHeapStatus()
**
** Revision 1.2 2005/07/30 09:00:20 x.cheng
** bug fix for kemalloc function...
**
** Revision 1.1.1.1 2005/07/27 06:53:16 x.cheng
** add into repositories
**
**
***************************************************************************/
#include "const.h"
#include "type.h"
#include "stdarg.h"
#include "stdlib.h"
#include "..\..\Inc\i386\map.h" //kernel\inc\i386
#include "..\..\Inc\i386\system.h"
#include "..\..\Inc\i386\page.h"
#include "..\..\Inc\tui.h"
#include "..\..\Inc\pmm.h"
#include "..\..\Inc\mts.h"
#include "..\..\Inc\keyb.h"
#include "..\..\Inc\debug.h"
#define __VMM_SRC__
#include "..\inc\def_vmm.h" //kernel\vmm\inc
/* debug preprocessor instrument
#ifdef _DEBUG__
#ifdef _DEBUG_VMM__
#endif
#endif
***************************/
/************************************************************
*************************************************************
** Function Name: pvVm1KeMalloc
** Author: x.cheng
**
** Comment:
** 从内核堆内存空间分配内存,使用First-Fit算法
**
**
**
** List of parameters:
** unsigned long - 需要分配内存的大小
** int - 分配内存后要做的动作
** Return value:
** 指向已分配内存空间的首指针
**
** Revisions:
**
*************************************************************
*************************************************************/
void *pvVm1KeMalloc(unsigned long ulSize, int iFlag)
{
ts_MCB *pstSearch, *pstBest=NULL;
unsigned long ulFlags;
if (!ulSize) return NULL; //0 size
// 实际分配中,应该+sizeof(ts_MCB),最小的分配的单位也是sizeof(ts_MCB)
ulSize = ( ulSize & -(sizeof(ts_MCB)) ) + sizeof(ts_MCB);
pstSearch = (ts_MCB*)KERNEL_HEAP_START_ADDRESS;
#ifdef _DEBUG__
#ifdef _DEBUG_VMM__
// POSITION();
#endif
#endif
SaveEflagsAndCli(ulFlags); //macro in system.h
while (pstSearch < (ts_MCB *)KERNEL_HEAP_END_ADDRESS) {
/* find a free block */
if ( MB_FREE == pstSearch->ulFlags ) {
// block is free, then...
if ( pstSearch->ulSize >= ulSize ) {
//found an enough block, lucky
pstBest = pstSearch;
break;
}
}
//examine the next memory block
pstSearch = (void *)pstSearch + pstSearch->ulSize + sizeof(ts_MCB);
}
#ifdef _DEBUG__
#ifdef _DEBUG_VMM__
// POSITION();
#endif
#endif
//have you found a free block?
if ( NULL == pstBest ) {
//out of memroy
RestoreEflags(ulFlags);
return NULL;
}
//if the block greater then ulSize, split it
if (pstBest->ulSize != ulSize) {
ts_MCB *pstNew = (void *)pstBest + sizeof (ts_MCB) + ulSize;
pstNew->ulMagic = MCB_MAGIC;
pstNew->ulFlags = MB_FREE;
pstNew->ulSize = pstBest->ulSize - ulSize - sizeof(ts_MCB);
pstNew->ulOwnerPtr = NULL;
pstBest->ulSize = ulSize;
}
//allocate the block and busy it
pstBest->ulMagic = MCB_MAGIC;
pstBest->ulFlags = MB_BUSY;
if( iFlag == GFP_KERNEL ) {
if ( g_pstCurrentTask == NULL )
pstBest->ulOwnerPtr = NULL; //fake....
else
pstBest->ulOwnerPtr = g_pstCurrentTask->iPid;
} else {
// kmalloc() during interrupt! the owner is ambiguous.
pstBest->ulOwnerPtr = NULL;
}
#ifdef _DEBUG__
#ifdef _DEBUG_VMM__
kprintf("%s(): size= %ld at %p\n", __FUNCTION__, ulSize, pstBest);
#endif
#endif
//kprintf("%s(): size= %ld at %p\n", __FUNCTION__, ulSize, pstBest);
//return the first-fit pointer
pstBest = (void*)pstBest + sizeof(ts_MCB);
RestoreEflags(ulFlags);
/* 返回的地址中刚刚除掉了MCB */
return (void *)pstBest;
}
/************************************************************
*************************************************************
** Function Name: vVm1KeFree
** Author: x.cheng
**
** Comment:
** 释放由pvKeMalloc分配的堆内存
** 并尽可能的把邻接空闲分区合并
**
**
** List of parameters:
** void * - 指向由pvKeMalloc分配的内存
**
** Return value:
** none
**
** Revisions:
**
*************************************************************
*************************************************************/
void vVm1KeFree(void *pvPtr)
{
ts_MCB *pstSearch, *pstNext, *pstPre;
unsigned long ulFlags;
if ( NULL == pvPtr ) return;
//pointer to the header
pstSearch = (void *)pvPtr - sizeof(ts_MCB);
if ( MCB_MAGIC != pstSearch->ulMagic ) return;
if ( MB_BUSY != pstSearch->ulFlags ) return;
#ifdef _DEBUG__
#ifdef _DEBUG_VMM__
kprintf("%s(): size= %ld at %p\n", __FUNCTION__, pstSearch->ulSize, pstSearch);
#endif
#endif
SaveEflagsAndCli(ulFlags);
pstSearch->ulFlags = MB_FREE;
pstSearch->ulOwnerPtr = NULL;
//try to combine the block with the next one
pstNext = (void *)pstSearch + pstSearch->ulSize + sizeof(ts_MCB);
if (pstNext < (ts_MCB *)KERNEL_HEAP_END_ADDRESS ) {
if ( MB_FREE == pstNext->ulFlags ) {
//merge the two block
pstSearch->ulSize += pstNext->ulSize + sizeof(ts_MCB);
pstNext->ulMagic = NULL;
}
}
//try to combine the block with the pre one
if (pstSearch != (ts_MCB *)KERNEL_HEAP_START_ADDRESS ) {
//find the pre block
pstPre = (ts_MCB *)KERNEL_HEAP_START_ADDRESS;
for(;;) {
if ( ((void *)pstPre + pstPre->ulSize + sizeof(ts_MCB)) == pstSearch ) {
//block found!
if ( MB_FREE == pstPre->ulFlags ) {
//and it's a free block
//merge them
pstPre->ulSize += (pstSearch->ulSize + sizeof(ts_MCB));
pstSearch->ulMagic = NULL;
pstSearch = pstPre;
}
break;
}
pstPre = (void *)pstPre + pstPre->ulSize + sizeof(ts_MCB);
}
}
//Release the physical space occupied by the block
{ //deallocate(pstSearch);
unsigned long ulStart = ulPageUpAlign( (unsigned long)((void *)pstSearch + sizeof(ts_MCB)) );
unsigned long ulEnd = ulPageDownAlign( (unsigned long)((void *)pstSearch + sizeof(ts_MCB) + pstSearch->ulSize) );
while( ulStart < ulEnd) {
if ( *pulAddressToPde(ulStart) != NULL) {
vPmmFreeOnePage(ulStart);
ulStart += PAGE_SIZE;
} else {
ulStart = ulPageDirUpAlign(ulStart);
}
}
}
RestoreEflags(ulFlags);
}
/************************************************************
*************************************************************
** Function Name: pvVm1KeAlignMalloc
** Author: x.cheng
**
** Comment:
** 分配的堆内存,按要求对齐
** exception: out of memory
**
** List of parameters:
** ulAlign - 对齐边界
** ulSize - 分配空间的大小
** iFlags -
**
** Return value:
** A pointer to a memory area aligned to the boundary.
** 返回的内存地址总是在ulAlign的边界上的!比如0xD0001000
** Revisions:
**
*************************************************************
*************************************************************/
void *pvVm1KeAlignMalloc(unsigned long ulAlign, unsigned long ulSize, int iFlags)
{
ts_MCB *pstTmp1, *pstTmp2;
if (!ulSize) return NULL;
//malloc invoke
pstTmp1 = (ts_MCB *)pvVm1KeMalloc(ulSize+ulAlign+2*sizeof(ts_MCB), iFlags);
if (NULL == pstTmp1) return NULL;
if ( 0 == ulAlign ) return (void *)pstTmp1;
//看看对齐了吗?
if ( (unsigned long)pstTmp1 % ulAlign ) {
//对齐它...
unsigned long ulFlags;
SaveEflagsAndCli(ulFlags);
//new allocate
pstTmp2 = pstTmp1 + 2;
pstTmp2 = (ts_MCB *)pulAlignUp( (unsigned long)pstTmp2, ulAlign) - 1;
pstTmp2->ulMagic = MCB_MAGIC;
pstTmp2->ulFlags = (pstTmp1-1)->ulFlags;
pstTmp2->ulOwnerPtr = (pstTmp1-1)->ulOwnerPtr;
//p2->size = mem_sizeof(p) - ((size_t)(p2+1) - (size_t)p);
pstTmp2->ulSize = (pstTmp1-1)->ulSize - ( (unsigned long)(pstTmp2+1) - (unsigned long)pstTmp1);
// free the unuse space.
(pstTmp1-1)->ulSize = (unsigned long)pstTmp2 - (unsigned long)pstTmp1;
RestoreEflags(ulFlags);
vVm1KeFree( (void *)pstTmp1 );
#ifdef _DEBUG__
#ifdef _DEBUG_VMM__
kprintf("%s(): size= %ld align= %d, at %p\n", __FUNCTION__, ulSize, ulAlign, pstTmp2+1);
#endif
#endif
return( pstTmp2 + 1 );
}
#ifdef _DEBUG__
#ifdef _DEBUG_VMM__
kprintf("%s(): size= %ld align= %d, at %p\n", __FUNCTION__, ulSize, ulAlign, pstTmp1);
#endif
#endif
//对齐了的!
return (pstTmp1);
}
/************************************************************
*************************************************************
** Function Name: vVm1KeMallocInit
** Author: x.cheng
**
** Comment:
** 内核堆内存分配初始化
**
**
**
** List of parameters:
** -
**
** Return value:
** no
**
** Revisions:
**
*************************************************************
*************************************************************/
void vVm1KeMallocInit()
{
ts_MCB *pstFirstMCB;
#ifdef _DEBUG__
#ifdef _DEBUG_VMM__
kprintf("\t--initial alloctor for kernel heap area...");
vDbgDummy();
#endif
#endif
vSTI();
// Create only one hudge block //
pstFirstMCB = (ts_MCB*)KERNEL_HEAP_START_ADDRESS;
pstFirstMCB->ulMagic = MCB_MAGIC;
pstFirstMCB->ulFlags = MB_FREE;
pstFirstMCB->ulSize = KERNEL_HEAP_END_ADDRESS - KERNEL_HEAP_START_ADDRESS - sizeof(ts_MCB);
pstFirstMCB->ulOwnerPtr = NULL;
}
/************************************************************
*************************************************************
** Function Name: Vm1KeDumpHeapStatus
** Author: x.cheng
**
** Comment:
** dump heap的分配情况
**
**
**
** List of parameters:
** -
**
** Return value:
** no
**
** Revisions:
**
*************************************************************
*************************************************************/
void Vm1KeDumpHeapStatus(void)
{
ts_MCB *pstSearch;
unsigned long ulFlags;
int iRow;
pstSearch = (ts_MCB*)KERNEL_HEAP_START_ADDRESS;
kprintf("\nMCB\t\tflags\t\tsize\t\towner\n");
SaveEflagsAndCli(ulFlags); //macro in io.h
while (pstSearch < (ts_MCB *)KERNEL_HEAP_END_ADDRESS) {
kprintf("%p\t\t%ld\t\t%ld\t\t%ld\n", pstSearch, pstSearch->ulFlags, pstSearch->ulSize, pstSearch->ulOwnerPtr);
if ( ++iRow > 21 ) {
kprintf("Press any key to continue, CTRL+C exit...\n");
if( iKeybGetChar() == CTRL_C )
break;
iRow = 0;
}
//examine the next memory block
pstSearch = (void *)pstSearch + pstSearch->ulSize + sizeof(ts_MCB);
}
kprintf("====================================================================\n");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -