⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vmm.c

📁 语法分析器 完成从c/c++向C++转变
💻 C
📖 第 1 页 / 共 2 页
字号:
    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 + -