home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / mslang / vm / src / vmalloc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-15  |  7.1 KB  |  259 lines

  1. /***
  2. * vmalloc.c -
  3. *
  4. *       Copyright (c) 1989-1992, Microsoft Corporation.  All rights reserved.
  5. *
  6. *Purpose:
  7. *
  8. * PUBLIC Functions:
  9. *
  10. *       FVmAllocatePageVp
  11. *       This function will allocate a virtual page at a specific
  12. *       virtual address.  The page must not allocated already.
  13. *
  14. *       VpVmAllocateCb
  15. *       This function allocates a block of pages large enough to store
  16. *       therequested number of bytes and returns the virtual address of
  17. *       this allocation.
  18. *
  19. *       VpVmAllocatePage
  20. *       This function allocates a virtual page and returns the address
  21. *       ofthis allocation.
  22. *
  23. * LOCAL Functions:
  24. *
  25. *       FVmAllocatePageHelper
  26. *       This function is an internal routine allocates a virtual page
  27. *       data specific address and assigns swap storage if appropriate.
  28. *
  29. *******************************************************************************/
  30.  
  31. #pragma title("Virtual Memory Manager")
  32. #pragma subtitle("Core routines")
  33.  
  34. #include <version.h>
  35. #include <vmassert.h>
  36. #include <system.h>
  37. #include <error.h>
  38. #include <vm.h>
  39. #include <vmp.h>
  40. #include <vmlist.h>
  41.  
  42. #include <stdlib.h>
  43.  
  44.  
  45. extern VPVOID _vpAllocNext;
  46.  
  47. int      _near _fVmSwapping = TRUE;    
  48.  
  49. extern PFBD _pfbdVirtHead;
  50. extern PFBD _pfbdVirtCurr;
  51. extern unsigned long _cVirtPageMax;
  52.  
  53. #pragma page()
  54.  
  55. int LOCAL __FVmAllocatePageHelper(PPTE ppte, VPVOID vp)
  56. {
  57.    VmTracePrintf(("FVmAllocatePageHelper: vp = %08lX.\n", vp));
  58.  
  59.    Assert(!(*ppte & (fAllocatedPte | fXmsPte | fDiskPte)));
  60.  
  61.  
  62.    /* If swap storage has already been allocated for this */
  63.    /* virtual page then just go ahead and use it. */
  64.  
  65.    if (*ppte & (fEmsPte | fXmsPte | fDiskPte))
  66.    {
  67.       *ppte |= fAllocatedPte | fUnreferencedPte;
  68.  
  69.       return(TRUE);
  70.    }
  71.  
  72.  
  73.    Assert(*ppte == 0);
  74.  
  75.    if (!_fVmSwapping)
  76.    {
  77.       HPGD     hpgd;
  78.       unsigned ipgd;
  79.  
  80.       /* Note: The following call to HpgdVmAllocate may invalidate the */
  81.       /* Note: ppte parameter.  However, if the call fails, then no */
  82.       /* Note: physical memory movement occured and the ppte parameter is */
  83.       /* Note: still valid and can be used to reset the allocated flag. */
  84.  
  85.       *ppte = fAllocatedPte | fUnreferencedPte;
  86.  
  87.       if ((hpgd = __HpgdVmAllocate(1)) != hpgdNil)
  88.       {
  89.      PpgdOfHpgd(hpgd)->vp = vp;
  90.      PpgdOfHpgd(hpgd)->pte = fAllocatedPte;
  91.      PpgdOfHpgd(hpgd)->hpgdHashNext = _rghpgdHash[ipgd = IpgdHashOfVp(vp)];
  92.      _rghpgdHash[ipgd] = hpgd;
  93.      return(TRUE);
  94.       }
  95.  
  96.       *ppte = 0;
  97.  
  98.       _fVmSwapping = TRUE;
  99.    }
  100.  
  101.    /* Once swapping starts, all pages must be assigned swap storage */
  102.    /* before the allocation can be considered successful. */
  103.  
  104.    /* Note: It is necessary to ensure that swap storage is available for */
  105.    /* Note: every virtual page that is allocated or else it isn't */
  106.    /* Note: meaningful to assume that a successful virtual memory */
  107.    /* Note: allocation implies that the virtual memory is available. */
  108.  
  109.    if (!__FVmAllocateEmsPage(ppte, vp))
  110.       if (!__FVmAllocateXmsPage(ppte))
  111.      if (!__FVmAllocateDiskPage(ppte))
  112.      {
  113.         Assert(*ppte == 0);
  114.  
  115.         return(FALSE);          /* Can't allocate physical page */
  116.      }
  117.  
  118.    Assert((*ppte & fAllocatedPte) && (*ppte & (fEmsPte | fXmsPte | fDiskPte)));
  119.  
  120.    return(TRUE);
  121. }
  122.  
  123. #pragma page()
  124.  
  125. int PUBLIC __FVmAllocatePageVp(VPVOID vp)
  126. {
  127.    VPPTE vppte;
  128.    PPTE  ppte;
  129.    PPT   ppt;
  130.  
  131.    /*
  132.     *  Virtual memory is organized into two types.  The lower region
  133.     *  of memory is occupied by page table pages. Page tables describe
  134.     *  pages of virtual memory and how to access those pages.  Even
  135.     *  the page tables themselves are described by other page tables.
  136.     *  The page tables are handled by the virtual memory manager and
  137.     *  should not be accessed by the application.  The remainder of
  138.     *  virtual memory is reserved for the application.
  139.     *
  140.     *  The page tables are split into two levels.  The first level of
  141.     *  page table pages describe themselves and all other page tables.
  142.     *  The second level of page tables describe the application region
  143.     *  of the virtual address space.  In this implementation, the first
  144.     *  level of page tables is limited to one page.  Based on a page
  145.     *  size of 2048 bytes and a page table entry size of four bytes,
  146.     *  the virtual memory region reserved for both levels of page tables
  147.     *  is 1 megabyte.  This also imposes a limit of 511 megabytes on the
  148.     *  application region of virtual memory.
  149.     *
  150.     *  In order to allocate a page at a specific virtual address in the
  151.     *  application region, it is necessary to ensure that the page table
  152.     *  page describing this region is allocated.  The root page that
  153.     *  describes all page table pages is always allocated.
  154.     */
  155.  
  156.  
  157.    VmTracePrintf(("FVmAllocatePageVp: vp = %08lX.\n", vp));
  158.  
  159.    Assert(IbOfVp(vp) == 0);            /* Only whole pages can be allocated */
  160.    Assert((vp >= vpptMax) && (vp < vpMax));
  161.  
  162.  
  163.    vppte = VppteOfVp(vp);              /* Virtual address of page table entry */
  164.    ppte = &_ptRoot[PageOfVp(vppte)];
  165.  
  166.    if (!(*ppte & fAllocatedPte))
  167.    {
  168.       unsigned iPage;
  169.  
  170.       /* The page table that describes the page to be allocated has not */
  171.       /* yet been allocated.  Allocate this page and initialize it. */
  172.  
  173.       if (!__FVmAllocatePageHelper(ppte, VpPageOfVp(vppte)))
  174.             return(FALSE);
  175.  
  176.       ppt = __PVmLoadVp(VpPageOfVp(vppte), TRUE);
  177.  
  178.       for (iPage = 0; iPage < (cbVmPage / sizeof(PTE)); iPage++)
  179.      (*ppt)[iPage] = (PTE) 0;
  180.    }
  181.  
  182.  
  183.    ppte = __PVmLoadVp(vppte, TRUE);
  184.    Assert(ppte != NULL);
  185.    if (ppte == NULL)                   /* Can't load page table */
  186.       return(FALSE);
  187.  
  188.    if (*ppte & fAllocatedPte)          /* Page already allocated */
  189.       return(FALSE);
  190.  
  191.    return(__FVmAllocatePageHelper(ppte, vp));
  192. }
  193.  
  194. #pragma page()
  195.  
  196. VPVOID PUBLIC __VpVmAllocateCb(unsigned long cb)
  197. {
  198.    unsigned long cPage;
  199.    VPVOID   vp;
  200.    VPVOID   vpT;
  201.    unsigned long iPage;
  202.     unsigned fNewAlloc = 0;
  203.  
  204.    VmTracePrintf(("VpVmAllocateCb: cb = %08lX.\n", cb));
  205.  
  206.    Assert(cb != 0);
  207.  
  208.    cPage = (unsigned) ((cb + cbVmPage - 1UL) / cbVmPage);
  209.  
  210.     Assert(cPage > 0);
  211.  
  212.     // reallocate freed VM pages
  213.     if (!__VmGetFreeBlock(&_pfbdVirtHead, &_pfbdVirtCurr, &_cVirtPageMax, cPage, &vp))
  214.     {
  215.         fNewAlloc = 1;
  216.         vp = _vpAllocNext;
  217.     }
  218.  
  219.     Assert (vp + cb < vpMax);
  220.  
  221. RetryAllocation:
  222.  
  223.     vpT = vp;
  224.    for (iPage = 0; iPage < cPage; iPage++)
  225.    {
  226.       if (!__FVmAllocatePageVp(vpT))
  227.       {
  228.             Assert(((vp & 16383UL) == 0) || (iPage == 0));
  229.  
  230. #if     VMFREE                         
  231.             for (; iPage > 0; iPage--)
  232.                 __VmFreePageVp(vpT -= cbVmPage);
  233. #endif  /* VMFREE */
  234.  
  235.             if (vp & 16383UL)
  236.                 if ((vp = (vp + 16383UL) & ~16383UL) != (VPVOID) 0)
  237.                     goto RetryAllocation;
  238.  
  239.             return(vpNil);
  240.       }
  241.  
  242.       vpT += cbVmPage;
  243.    }
  244.  
  245.     // if this was a 'new' allocation (as opposed to reusing vm space), 
  246.     // bump the global alloc pointer. If alloc fails, not changed.
  247.     if (fNewAlloc)
  248.         _vpAllocNext = vpT;
  249.  
  250.    return(vp);
  251. }
  252.  
  253. #pragma page()
  254.  
  255. VPVOID PUBLIC __VpVmAllocatePage(void)
  256. {
  257.    return(__VpVmAllocateCb(cbVmPage));
  258. }
  259.