📄 vmm.c
字号:
VMM_BLOCK_P pstSmallBlock = (VMM_BLOCK_P) NULL;
SHORT sSmallBytes = 0;
*ppstRetBlock = (VMM_BLOCK_P) NULL;
if(sType == VMM_STATE_MEMORY)
pstMember = pstVmmMgr -> pstMemList;
else
pstMember = pstVmmMgr -> pstFreeDiskBlocks;
/* find smallest available block */
while(pstMember != NULL)
{
pstMemberNext = pstMember -> psNext;
pstBlock = (VMM_BLOCK_P) pstMember -> pvData;
if((pstBlock -> sOwner == VMM_OWNER_NONE) &&
(pstBlock -> sBytes >= sBlockSize))
{
if(pstBlock -> sBytes == sBlockSize) /* exact match */
{
pstMemberBlock = pstMember;
pstSmallBlock = pstBlock;
sSmallBytes = pstBlock -> sBytes;
break;
}
/* initialize for first block found >= required size */
if(sSmallBytes == 0)
{
pstMemberBlock = pstMember;
pstSmallBlock = pstBlock;
sSmallBytes = pstBlock -> sBytes;
}
}
pstMember = pstMemberNext;
}
/* found candidate block */
if(pstSmallBlock != NULL)
{
fFoundBlock = C_TRUE;
pstBlock = pstSmallBlock;
/* check if must split */
sByteDiff = pstBlock -> sBytes - sBlockSize;
if(sByteDiff > 0)
{
/* split current block into two */
VmmSplitBlock(sType,pstBlock,sOwner,sBlockSize,ppstRetBlock);
}
else
{
/* found exact match */
if(pstVmmMgr -> pstReloadBlock != NULL)
{
/* if reloading from disk, remove this empty block */
pstVmmMgr -> pstReloadBlock -> pvBlock = pstBlock -> pvBlock;
/* different handling for disk vs memory */
if(sType == VMM_DISK)
{
/* if disk, am reusing block out there */
pstBlock -> sOwner = sOwner;
*ppstRetBlock = pstBlock;
}
else
{
/* if memory, a new block will be thrown away,
Reloading into existing block = ReloadBlock */
*ppstRetBlock = pstVmmMgr -> pstReloadBlock;
free(pstBlock);
MemLstDeleteMember(pstVmmMgr -> pstMemList,
pstMemberBlock,
&(pstVmmMgr -> pstMemList));
}
}
else
{
pstBlock -> sOwner = sOwner;
*ppstRetBlock = pstBlock;
}
}
}
C_RETURN
}
/*
** VmmSizeSwapToDisk
**
** Need sBytes of room for memory, swap whatever it takes
*/
#ifdef C_ANSI
SHORT
VmmSizeSwapToDisk(SHORT sBytes,SHORT sOwner,VMM_BLOCK_P * ppstBlock)
#else
SHORT
VmmSizeSwapToDisk(sBytes,sOwner,ppstBlock)
SHORT sBytes;
SHORT sOwner;
VMM_BLOCK_P * ppstBlock;
#endif
{
C_DEF_MODULE("VmmSizeSwapToDisk")
LLIST_P pstMember;
VMM_BLOCK_P pstBlock;
SHORT sAvailBytes = 0; /* total available bytes in memory block */
SHORT sByte2 = 0;
SHORT sEnoughBytes = 0; /* size of available contingous block */
VMM_BLOCK_P pstEnoughBlock; /* the block itself */
VMM_BLOCK_P pstNewBlock;
*ppstBlock = (VMM_BLOCK_P) NULL;
pstMember = pstVmmMgr -> pstMemList;
while(sAvailBytes < sBytes)
{
VmmFindStaleBlock(&pstBlock); /* find oldest block to swap out */
if(pstBlock == NULL)
{
VmmCheckFreeBlocks(&sByte2);
sAvailBytes += sByte2;
if(sAvailBytes >= sBytes)
break;
}
VmmSwapToDisk(pstBlock,sOwner); /* move block out to swap */
sAvailBytes += pstBlock -> sBytes; /* increment available */
if(pstBlock -> sBytes >= sBytes) /* see if big enough */
{
if(sEnoughBytes == 0)
{
sEnoughBytes = pstBlock->sBytes;
pstEnoughBlock = pstBlock;
}
else if(pstBlock->sBytes < sEnoughBytes) /* remember smallest */
{
sEnoughBytes = pstBlock->sBytes;
pstEnoughBlock = pstBlock;
}
}
}
/* have swapped out everything to get available memory */
if(sAvailBytes >= sBytes)
{
if(sEnoughBytes < sBytes) /* enough, but not contiguous, re-organize */
VmmCompress();
else
{
if(sEnoughBytes == sBytes) /* exact match on size */
{
VmmCreateBlock((SHORT) VMM_MEMORY,
sBytes,
sOwner,
pstEnoughBlock -> pvBlock, /* re-use memory */
0L,
&pstNewBlock);
*ppstBlock = pstNewBlock;
}
else
{
/* too big, break off a chunk */
VmmSplitBlock((SHORT) VMM_MEMORY,
pstEnoughBlock,
sOwner,
sBytes,
ppstBlock);
}
}
}
else
C_SET_STATUS(C_NOTOK);
C_RETURN
}
/*
** VmmSwapToDisk
**
** A specific block must be swapped to disk.
** Locate an available disk block large enough or create one.
*/
#ifdef C_ANSI
SHORT
VmmSwapToDisk(VMM_BLOCK_P pstVmmBlock,SHORT sOwner)
#else
SHORT
VmmSwapToDisk(pstVmmBlock,sOwner)
VMM_BLOCK_P pstVmmBlock;
SHORT sOwner;
#endif
{
C_DEF_MODULE("VmmSwapToDisk")
VMM_BLOCK_P pstBlock = NULL;
/* try and find existing vacant disk block to use */
VmmAssignBlock(VMM_DISK,pstVmmBlock -> sBytes,sOwner,&pstBlock);
/* if none, create new one */
if(pstBlock == NULL)
{
VmmCreateDiskBlock(pstVmmBlock -> sBytes,&pstBlock);
pstBlock -> sOwner = sOwner;
pstBlock -> lDescriptor = pstVmmBlock -> lDescriptor;
}
/* remember disk block so can remove ownership
when swapped back to memory */
pstVmmBlock -> pstMate = pstBlock;
/* give block in memory chain same offset as block in disk chain */
pstVmmBlock -> lOffset = pstBlock -> lOffset;
fseek(pstVmmMgr -> fpSwapFile,
pstVmmBlock -> lOffset,
0);
fwrite(pstVmmBlock -> pvBlock,
1,
pstVmmBlock -> sBytes,
pstVmmMgr -> fpSwapFile);
pstVmmBlock -> sState = VMM_STATE_DISK;
C_RETURN
}
/*
** VmmCreateDiskBlock
**
** Create a new disk block of a given size
*/
#ifdef C_ANSI
SHORT
VmmCreateDiskBlock(SHORT sBytes,VMM_BLOCK_P * ppstBlock)
#else
SHORT
VmmCreateDiskBlock(sBytes,ppstBlock)
SHORT sBytes;
VMM_BLOCK_P * ppstBlock;
#endif
{
C_DEF_MODULE("VmmCreateDiskBlock")
VMM_BLOCK_P pstBlock;
LLIST_P pstMember;
pstBlock = (VMM_BLOCK_P) calloc(1,sizeof(VMM_BLOCK_T));
pstBlock -> sBytes = sBytes;
pstBlock -> sOwner = VMM_OWNER_NONE;
pstBlock -> sState = VMM_DISK;
pstBlock -> lOffset = pstVmmMgr -> lSwapBytes;
pstVmmMgr -> lSwapBytes += (LONG) sBytes;
MemLstAllocMember(&pstMember);
pstMember -> pvData = (PVOID) pstBlock;
MemLstInsertMember(pstVmmMgr -> pstFreeDiskBlocks,
pstMember,
VmmCompareBlockSize,
&(pstVmmMgr -> pstFreeDiskBlocks));
*ppstBlock = pstBlock;
C_RETURN
}
/*
** VmmSplitBlock
**
** Split an existing block which is larger than needed into 2 blocks
** One will be the exact size needed, the remaining bytes will be
** allocated from a new block.
*/
#ifdef C_ANSI
SHORT
VmmSplitBlock(SHORT sType,
VMM_BLOCK_P pstOrigBlock,
SHORT sOwner,
SHORT sBlockSize,
VMM_BLOCK_P *ppstNewBlock)
#else
SHORT
VmmSplitBlock(sType,
pstOrigBlock,
sOwner,
sBlockSize,
ppstNewBlock)
SHORT sType;
VMM_BLOCK_P pstOrigBlock;
SHORT sOwner;
SHORT sBlockSize;
VMM_BLOCK_P *ppstNewBlock;
#endif
{
C_DEF_MODULE("VmmSplitBlock")
SHORT sRemBytes;
PVOID pvPtr;
LONG lOffset;
/* find size of remaining/new block */
sRemBytes = pstOrigBlock -> sBytes - sBlockSize;
/* calc new/reduced size of original block */
pstOrigBlock -> sBytes = sRemBytes;
if(sType == VMM_MEMORY)
{
pvPtr = (PVOID) ( (LONG) pstOrigBlock -> pvBlock +
(LONG) sRemBytes);
if(pstVmmMgr -> pstReloadBlock != NULL)
{
pstVmmMgr -> pstReloadBlock -> pvBlock = pvPtr;
*ppstNewBlock = pstVmmMgr -> pstReloadBlock;
}
else
VmmCreateBlock(sType,sBlockSize,sOwner,pvPtr,0L,ppstNewBlock);
}
else
{
lOffset = pstOrigBlock -> lOffset + sBlockSize;
VmmCreateBlock(sType,sBlockSize,sOwner,(PVOID) 0,lOffset,ppstNewBlock);
}
C_RETURN
}
/*
** VmmCreateBlock
**
** Create a new block (either disk or memory).
** Either the lOffset or pvPtr will be assigned
*/
#ifdef C_ANSI
SHORT VmmCreateBlock(SHORT sType,
SHORT sBlockSize,
SHORT sOwner,
PVOID pvPtr,
LONG lOffset,
VMM_BLOCK_P * ppstNewBlock)
#else
SHORT VmmCreateBlock(sType,
sBlockSize,
sOwner,
pvPtr,
lOffset,
ppstNewBlock)
SHORT sType;
SHORT sBlockSize;
SHORT sOwner;
PVOID pvPtr;
LONG lOffset;
VMM_BLOCK_P * ppstNewBlock;
#endif
{
C_DEF_MODULE("VmmCreateBlock")
VMM_BLOCK_P pstBlock;
LLIST_P pstMember;
pstBlock = (VMM_BLOCK_P) calloc(1,sizeof(VMM_BLOCK_T));
pstBlock -> lDescriptor = pstVmmMgr -> lDescriptor;
pstVmmMgr -> lDescriptor++;
pstBlock -> sBytes = sBlockSize;
pstBlock -> sOwner = sOwner;
pstBlock -> sState = sType;
pstBlock -> lTimeLastAccess = VmmCurTime();
if(sType = VMM_MEMORY)
pstBlock -> pvBlock = pvPtr;
else
pstBlock -> lOffset = lOffset;
MemLstAllocMember(&pstMember);
pstMember -> pvData = (PVOID) pstBlock;
if(sType == VMM_DISK)
{
MemLstInsertMember(pstVmmMgr -> pstFreeDiskBlocks,
pstMember,
VmmCompareBlockSize,
&(pstVmmMgr -> pstFreeDiskBlocks));
}
else
{
MemLstInsertMember(pstVmmMgr -> pstMemList,
pstMember,
VmmCompareBlockSize,
&(pstVmmMgr -> pstMemList));
}
*ppstNewBlock = pstBlock;
C_RETURN
}
/*
** VmmCompareBlockSize
**
** Compare function for use by MemLst for comparing memory blocks
*/
#ifdef C_ANSI
SHORT
VmmCompareBlockSize(PVOID pvData1, PVOID pvData2)
#else
SHORT
VmmCompareBlockSize(pvData1,pvData2)
PVOID pvData1;
PVOID pvData2;
#endif
{
VMM_BLOCK_P pstBlock1;
VMM_BLOCK_P pstBlock2;
pstBlock1 = (VMM_BLOCK_P) pvData1;
pstBlock2 = (VMM_BLOCK_P) pvData2;
if(pstBlock1 -> sBytes == pstBlock2 -> sBytes)
return(0);
else if(pstBlock1 -> sBytes > pstBlock2 -> sBytes)
return(-1);
else
return(1);
}
/*
** VmmCompareHandle
**
** Compare function for use by MemLst for comparing memory blocks
*/
#ifdef C_ANSI
SHORT
VmmCompareHandle(PVOID pvData1, PVOID pvData2)
#else
SHORT
VmmCompareHandle(pvData1,pvData2)
PVOID pvData1;
PVOID pvData2;
#endif
{
VMM_BLOCK_P pstBlock1;
VMM_BLOCK_P pstBlock2;
pstBlock1 = (VMM_BLOCK_P) pvData1;
pstBlock2 = (VMM_BLOCK_P) pvData2;
if(pstBlock1 -> lDescriptor == pstBlock2 -> lDescriptor)
return(0);
else if(pstBlock1 -> lDescriptor > pstBlock2 -> lDescriptor)
return(-1);
else
return(1);
}
/*
** VmmCurTime
**
** Get the current time, used in updated block access times
*/
#ifdef C_ANSI
LONG
VmmCurTime(VOID)
#else
LONG
VmmCurTime()
#endif
{
time_t lTime;
time(&lTime);
return((LONG) lTime);
}
/* *******************************************************************
T E S T C O D E
******************************************************************* */
#ifdef TEST
#define TEST_3
#define MAX_HANDLES 512
main()
{
LONG lHandle1;
LONG lHandle2;
PCHAR pcData;
SHORT sCnt;
LONG lHandle[MAX_HANDLES];
SHORT sCnt2;
VmmInit(1024,"swap.dat");
#ifdef TEST_1
VmmAlloc(1,100,&lHandle1);
VmmPrep(lHandle1,(PPVOID) &pcData);
strcpy(pcData,"Testing 123");
VmmAlloc(1,100,&lHandle2);
VmmPrep(lHandle2,(PPVOID) &pcData);
strcpy(pcData,"Testing 456");
VmmPrep(lHandle1,(PPVOID) &pcData);
printf("%s\n", pcData);
VmmPrep(lHandle2,(PPVOID) &pcData);
printf("%s\n", pcData);
VmmFree(lHandle1);
VmmFree(lHandle2);
#endif
#ifdef TEST_2
VmmAlloc(1,100,&lHandle1);
VmmAlloc(1,1000,&lHandle2);
VmmPrep(lHandle1, (PPVOID) &pcData);
strcpy(pcData,"lHandle1");
VmmPrep(lHandle2, (PPVOID) &pcData);
strcpy(pcData,"lHandle2");
for(sCnt = 0; sCnt < 10; sCnt++)
{
VmmPrep(lHandle1,(PPVOID) &pcData);
printf("%s\n", pcData);
sprintf(pcData,"Handle1 - %d", sCnt);
VmmPrep(lHandle2,(PPVOID) &pcData);
printf("%s\n", pcData);
sprintf(pcData,"Handle2 - %d", sCnt);
}
VmmFree(lHandle1);
VmmFree(lHandle2);
VmmTerm();
#endif
#ifdef TEST_3
for(sCnt = 0; sCnt < MAX_HANDLES; sCnt++)
VmmAlloc(1,16,&lHandle[sCnt]);
for(sCnt2 = 0; sCnt2 < MAX_HANDLES; sCnt2++)
{
printf("Writing...\n");
for(sCnt = 0; sCnt < MAX_HANDLES; sCnt++)
{
VmmPrep(lHandle[sCnt],&pcData);
sprintf(pcData,"Handle %d %d",sCnt,sCnt2);
}
printf("Retrieve Ascending...\n");
for(sCnt = 0; sCnt < MAX_HANDLES; sCnt++)
{
VmmPrep(lHandle[sCnt],&pcData);
printf("%s\n",pcData);
}
printf("Retrieve Descending...\n");
for(sCnt = MAX_HANDLES-1; sCnt > 0; sCnt--)
{
VmmPrep(lHandle[sCnt],&pcData);
printf("%s\n",pcData);
}
}
for(sCnt = 0; sCnt < MAX_HANDLES; sCnt++)
VmmFree(lHandle[sCnt]);
VmmTerm();
#endif
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -