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

📄 vmm.c

📁 语法分析器 完成从c/c++向C++转变
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************
*+
** Module Name:   Vmm.C
** 
** Description:   Virtual Memory Manager
**                  
**                Supports limited virtual memory management.
**
**                Performs cacheing of data and swapping to/from disk file.
**
**
** Written by:  John Tal
**
**
**
** Modification History:
**
** Date          Programmer      Mod#     Modification
** ---------------------------------------------------------------------------
** 17-FEB-1992   J. Tal          V1.0-000 New
**
*-
*/

#ifdef C_ANSI
#include <string.h>
#include <stdlib.h>
#endif

#ifdef C_UNIX
#include <sys/types.h>
#endif

#include <time.h>

#include <stdio.h>

#include <memlib.h>

#include <vmm.h>



VMM_MGR_T  stVmmMgr;
VMM_MGR_P  pstVmmMgr = &stVmmMgr;



/*
**   VmmInit
**
**       Initialize virtual memory manager
*/

#ifdef C_ANSI
SHORT
VmmInit(SHORT sMemoryBytes,PCHAR pcSwapFile)
#else
SHORT
VmmInit(sMemoryBytes,pcSwapFile)
SHORT sMemoryBytes;
PCHAR pcSwapFile;  
#endif 
{
   C_DEF_MODULE("VmmInit")

   static BOOL  fVmmInit;
   VMM_BLOCK_P  pstNewBlock;

   if(fVmmInit)
      C_LEAVE(VMM_ERR_INIT)

   memset(&stVmmMgr,0,sizeof(VMM_MGR_T));

   pstVmmMgr -> pvBlock = (PVOID) calloc(sMemoryBytes,1);
   pstVmmMgr -> lTotalBytes = sMemoryBytes;
   pstVmmMgr -> lSwapBytes = 0;

   if(pstVmmMgr -> pvBlock == NULL)
      C_LEAVE(VMM_ERR_MEM_EXCEEDED)

   strcpy(pstVmmMgr -> szSwapFile,pcSwapFile);


   pstVmmMgr -> fpSwapFile = fopen(pstVmmMgr -> szSwapFile,"w+b");

   if(pstVmmMgr -> fpSwapFile == NULL)
      C_LEAVE(VMM_ERR_INIT)


   /*  create logical block for all of memory */

   C_STATUS = VmmCreateBlock(VMM_MEMORY,sMemoryBytes,VMM_OWNER_NONE,pstVmmMgr -> pvBlock,0L,&pstNewBlock);

   
   if(pstVmmMgr -> fpSwapFile == NULL)
     C_LEAVE(VMM_ERR_SWAP_FILE)

   fVmmInit = C_TRUE;

C_MODULE_EXIT:
 
   C_RETURN
}


/*
**  VmmCompress
**
**  Compress Internal memory.  Called when there is enough space
**  but not in a single continuous block.
*/

#ifdef C_ANSI
SHORT
VmmCompress(VOID)
#else
SHORT
VmmCompress()
#endif 
{
   C_DEF_MODULE("VmmCompress")

   VMM_BLOCK_P  pstNewBlock;
   VMM_BLOCK_P  pstBlock;
   PVOID   pvNewBlock;
   PVOID   pvPtr;
   LLIST_P pstMember;
   LONG    lUseBytes = 0;
   LONG    lRemBytes;
   LLIST_P pstMemberNext;   

   /* get new block of memory */

   pvNewBlock = (PVOID) calloc(1,(SHORT) pstVmmMgr -> lTotalBytes);

   if(pvNewBlock == NULL)
      C_LEAVE(VMM_ERR_MEM_EXCEEDED)

   pvPtr = pvNewBlock;

   /* look at all memory blocks */
 
   pstMember = pstVmmMgr -> pstMemList;

   while(pstMember != NULL)
   {
      pstBlock = (VMM_BLOCK_P) pstMember -> pvData;

      pstMemberNext = pstMember -> psNext;

      /* if active, copy into new master block
                    reset block pointer
                    increment current pointer into new block
                    increment used bytes
      */

      if(pstBlock -> sOwner != VMM_OWNER_NONE)
      {
         if(pstBlock -> sState == VMM_STATE_MEMORY)
         {
            /* retain by copying into new master bloc */

            memcpy(pvPtr,pstBlock -> pvBlock, pstBlock -> sBytes);
            pstBlock -> pvBlock = pvPtr;
            pvPtr = (PVOID) ((long) pvPtr + (long) pstBlock -> sBytes);
            lUseBytes += pstBlock -> sBytes;
         }
      }
      else
      {
         /* free block and remove control list member */

         free(pstBlock);

         MemLstDeleteMember(pstVmmMgr -> pstMemList,
                            pstMember,
                            &(pstVmmMgr -> pstMemList));

      }

      pstMember = pstMemberNext;
   }

   /* free old block and make Vmm point to new */

   free(pstVmmMgr -> pvBlock);
   pstVmmMgr -> pvBlock = pvNewBlock;

   lRemBytes = pstVmmMgr -> lTotalBytes - lUseBytes;
    
   
   C_STATUS = VmmCreateBlock((SHORT) VMM_MEMORY,
                             (SHORT) lRemBytes,
                             (SHORT) VMM_OWNER_NONE,
                             pvPtr,
                             (LONG) 0,
                             &pstNewBlock);

C_MODULE_EXIT:

      ;

   C_RETURN
}
 
 


/*
**  VmmAlloc - Process wants a memory block
*/

#ifdef C_ANSI
SHORT
VmmAlloc(SHORT sOwner,SHORT sTotalBytes,PLONG plHandle)
#else
SHORT
VmmAlloc(sOwner,sTotalBytes,plHandle)
SHORT sOwner;
SHORT sTotalBytes;
PLONG plHandle;
#endif
{
   C_DEF_MODULE("VmmAlloc")

   VMM_BLOCK_P  pstBlock = (VMM_BLOCK_P) NULL;


   if((LONG) sTotalBytes > pstVmmMgr -> lTotalBytes)
      C_LEAVE(VMM_ERR_MEM_EXCEEDED)

   while(pstBlock == NULL)
   {
      VmmAssignBlock(VMM_MEMORY,sTotalBytes,sOwner,&pstBlock);
      if(pstBlock == NULL)
         VmmSizeSwapToDisk(sTotalBytes,sOwner,&pstBlock);
   }

   /* update access time */

   pstBlock -> lTimeLastAccess = VmmCurTime();


   *plHandle = pstBlock -> lDescriptor;

C_MODULE_EXIT:
   
    ;

   C_RETURN
}



/*
**  VmmPrep
**  
**  Setup Memory block before access to ensure is in memory
**  Also call before each access to update access times used
**  in cacheing decisions.
*/

#ifdef C_ANSI
SHORT
VmmPrep(LONG lHandle,PPVOID ppvVirtualPtr)
#else
SHORT
VmmPrep(lHandle,ppvVirtualPtr)
LONG lHandle;
PPVOID ppvVirtualPtr;
#endif
{

   C_DEF_MODULE("VmmPrep")

   LLIST_P  pstMember;
   VMM_BLOCK_P  pstVmmBlock;

   MemLstFindMember(pstVmmMgr -> pstMemList,
                    (PVOID) &lHandle,
                    VmmCompareHandle,
                    &pstMember);

   if(pstMember != NULL)
   {
      pstVmmBlock = (VMM_BLOCK_P) pstMember -> pvData;

      if(pstVmmBlock -> sState == VMM_STATE_DISK)
      {
         pstVmmMgr -> pstReloadBlock = pstVmmBlock;

         VmmLoadFromDisk(pstVmmBlock,pstVmmBlock -> sOwner);

         pstVmmMgr -> pstReloadBlock = (VMM_BLOCK_P) NULL;
      
      }

      /* update access time */

      pstVmmBlock -> lTimeLastAccess = VmmCurTime();

      *ppvVirtualPtr = pstVmmBlock -> pvBlock;

   }

   C_RETURN
}
      

/*
**  VmmFree
**
**  Process is freeing an allocated block
*/

#ifdef C_ANSI
SHORT
VmmFree(LONG lDescriptor)
#else
SHORT
VmmFree(lDescriptor)
LONG lDescriptor;
#endif
{
   C_DEF_MODULE("VmmFree")

   LLIST_P  pstMember;
   VMM_BLOCK_P  pstBlock;

   pstMember = pstVmmMgr -> pstMemList;

   while(pstMember != NULL)
   {
      pstBlock = (VMM_BLOCK_P) pstMember -> pvData;
 
      if(pstBlock -> lDescriptor == lDescriptor)
      {
         pstBlock -> sOwner = VMM_OWNER_NONE;
         
         /* take care of disk block if swapped out */

         if(pstBlock -> pstMate != NULL)
         {
            pstBlock -> pstMate -> sOwner = VMM_OWNER_NONE;
         }

         break;
      }

      pstMember = pstMember -> psNext;
   }


   if(pstMember == NULL)
      C_SET_STATUS(C_NOTOK)

   C_RETURN
}


/*
**  VmmTerm
**
**  Terminate Small Memory Manager
*/

#ifdef C_ANSI
SHORT VmmTerm(VOID)
#else
SHORT VmmTerm()
#endif
{
   C_DEF_MODULE("VmmTerm")

   
   LLIST_P pstMember;
   LLIST_P pstMemberNext;
   VMM_BLOCK_P  pstBlock;

    
   fclose(pstVmmMgr -> fpSwapFile);

  
   /* free main memory block */

   free(pstVmmMgr -> pvBlock);


   /* free all sub-alloc memory blocks */
   
   pstMember = pstVmmMgr -> pstMemList;

   while(pstMember != NULL)
   {
      pstBlock = (VMM_BLOCK_P) pstMember -> pvData;

      pstMemberNext = pstMember -> psNext;

      free(pstBlock);

      pstMember = pstMemberNext;
   }



   /* free all disk swap blocks */

   pstMember = pstVmmMgr -> pstFreeDiskBlocks;

   while(pstMember != NULL)
   {
      pstBlock = (VMM_BLOCK_P) pstMember -> pvData;

      pstMemberNext = pstMember -> psNext;

      free(pstBlock);

      pstMember = pstMemberNext;
   }

   C_RETURN     
}



/*
**   VmmLoadFromDisk
**
**   A block has been swapped to disk, load it back into memory
*/

#ifdef C_ANSI
SHORT
VmmLoadFromDisk(VMM_BLOCK_P pstVmmBlock,SHORT sOwner)
#else
SHORT
VmmLoadFromDisk(pstVmmBlock,sOwner)
VMM_BLOCK_P pstVmmBlock;
SHORT sOwner;
#endif
{
   C_DEF_MODULE("VmmLoadFromDisk")

   VMM_BLOCK_P  pstBlock = NULL;


      
   while(pstBlock == NULL)
   {
      VmmAssignBlock(VMM_MEMORY,pstVmmBlock -> sBytes,sOwner,&pstBlock);
      if(pstBlock == NULL)
         VmmSizeSwapToDisk(pstVmmBlock -> sBytes,sOwner,&pstBlock);
   }

 
   if(pstBlock != pstVmmBlock)
   {
      /* problem here, another block has been created, must merge two 
         together.  All we really need is the pvBlock ptr */

      pstVmmBlock -> pvBlock = pstBlock -> pvBlock;

      /* remove newly created block */
      VmmVanishBlock(VMM_MEMORY,pstBlock);
   }


   fseek(pstVmmMgr -> fpSwapFile,
         pstVmmBlock -> lOffset,
         0);

   fread(pstVmmBlock -> pvBlock,
         1,
         pstVmmBlock -> sBytes,
         pstVmmMgr -> fpSwapFile);

   pstVmmBlock -> sState = VMM_STATE_MEMORY;


   /* free up disk block for other use */

   if(pstVmmBlock -> pstMate != NULL)
   {
      pstVmmBlock -> pstMate -> sOwner = VMM_OWNER_NONE;
      pstVmmBlock -> pstMate = NULL;
   }

   C_RETURN
}


/*
**   VmmVanishBlock
**
**   A new block has been created during processing and is not needed
**   (pvBlock was probably copied before this call)
*/

#ifdef C_ANSI
SHORT
VmmVanishBlock(SHORT sType,VMM_BLOCK_P pstVanishBlock)
#else
SHORT
VmmVanishBlock(sType,pstVanishBlock)
SHORT sType;
VMM_BLOCK_P pstVanishBlock;
#endif
{
  C_DEF_MODULE("VmmVanishBlock")

  LLIST_P  pstMember;
  VMM_BLOCK_P  pstBlock;

  if(sType == VMM_STATE_MEMORY)
     pstMember = pstVmmMgr -> pstMemList;
  else
     pstMember = pstVmmMgr -> pstFreeDiskBlocks;

  while(pstMember != NULL)
  {
     pstBlock = (VMM_BLOCK_P) pstMember -> pvData;  

     if(pstBlock == pstVanishBlock)
     {
        if(sType == VMM_MEMORY)
        {
           C_STATUS = MemLstDeleteMember(pstVmmMgr -> pstMemList,
                                         pstMember,
                                         &(pstVmmMgr -> pstMemList));
        }
        else
        {
           C_STATUS = MemLstDeleteMember(pstVmmMgr -> pstFreeDiskBlocks,
                                         pstMember,
                                         &(pstVmmMgr -> pstFreeDiskBlocks));
        }
        
        break;
     }

     pstMember = pstMember -> psNext;

  }

  
  free(pstVanishBlock);

  C_RETURN
}


/*
**   VmmCheckFreeBlocks
**
**   Check total bytes available across all free fragments
*/

#ifdef C_ANSI
SHORT
VmmCheckFreeBlocks(SHORT * pAvail)
#else
SHORT
VmmCheckFreeBlocks(pAvail)
SHORT * pAvail;
#endif
{
   C_DEF_MODULE("VmmCheckFreeBlocks")

   LLIST_P  pstMember;
   VMM_BLOCK_P  pstBlock;
   SHORT  sFreeBytes = 0;

   pstMember = pstVmmMgr -> pstMemList;

   /* find oldest available block */

   while(pstMember != NULL)
   {
      /*  if unused block, count it */
     
      pstBlock = (VMM_BLOCK_P) pstMember -> pvData;

      if((pstBlock -> sOwner == VMM_OWNER_NONE) &&
         (pstBlock -> sState == VMM_STATE_MEMORY))
      {
         sFreeBytes += pstBlock -> sBytes; 
      }

      pstMember = pstMember -> psNext;

  }

  *pAvail = sFreeBytes;

  return(C_OK);
}


/*
**  VmmFindStaleBlock
*/

#ifdef C_ANSI
SHORT
VmmFindStaleBlock(VMM_BLOCK_P * ppstRetBlock)
#else
SHORT
VmmFindStaleBlock(ppstRetBlock)
VMM_BLOCK_P * ppstRetBlock;
#endif
{
   C_DEF_MODULE("VmmFindStaleBlock")

   LLIST_P  pstMember;
   LLIST_P  pstMemberNext;

   VMM_BLOCK_P  pstBlock;
   VMM_BLOCK_P  pstOldBlock = (VMM_BLOCK_P) NULL;
   LONG     lTimeLastAccess;


   lTimeLastAccess = VmmCurTime();

   *ppstRetBlock = (VMM_BLOCK_P) NULL;

   pstMember = pstVmmMgr -> pstMemList;

   /* find oldest available block */

   while(pstMember != NULL)
   {
      pstMemberNext = pstMember -> psNext;

      pstBlock = (VMM_BLOCK_P) pstMember -> pvData;

      if((pstBlock -> sOwner != VMM_OWNER_NONE) &&
         (pstBlock -> sState != VMM_STATE_DISK))
      {
         if(pstBlock -> lTimeLastAccess <= lTimeLastAccess) 
         { 
            pstOldBlock = pstBlock;
            lTimeLastAccess = pstBlock -> lTimeLastAccess;
         }
      }

      pstMember = pstMemberNext;
   }

   *ppstRetBlock = pstOldBlock;

   return(C_OK);
}



/*
**   VmmAssignBlock
**
**   Find and assign a block for either memory or disk allocation
**   Can return NULL in the return block if none found
*/

#ifdef C_ANSI
SHORT
VmmAssignBlock(SHORT sType,
               SHORT sBlockSize,
               SHORT sOwner,
               VMM_BLOCK_P * ppstRetBlock)
#else
SHORT
VmmAssignBlock(sType,
               sBlockSize,
               sOwner,
               ppstRetBlock)
SHORT sType;
SHORT sBlockSize;
SHORT sOwner;
VMM_BLOCK_P * ppstRetBlock;
#endif
{
    C_DEF_MODULE("VmmAssignBlock")

    LLIST_P  pstMember;
    LLIST_P  pstMemberNext;
    LLIST_P  pstMemberBlock;

    VMM_BLOCK_P  pstBlock;
    BOOL     fFoundBlock = C_FALSE;
    SHORT    sByteDiff;


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -