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

  1. /***
  2. * vmems.c -
  3. *
  4. *       Copyright (c) 1989-1992, Microsoft Corporation.  All rights reserved.
  5. *
  6. *Purpose:
  7. *
  8. * PRIVATE Functions:
  9. *
  10. *       VmInitializeEms:
  11. *
  12. *       VmTerminateEms:
  13. *
  14. *       FVmAllocateEmsPage:
  15. *
  16. *       VmMapInEmsPage:
  17. *
  18. *******************************************************************************/
  19.  
  20. #pragma title("Virtual Memory Manager")
  21. #pragma subtitle("DOS Expanded memory support")
  22.  
  23.  
  24. #include <version.h>
  25. #include <vmassert.h>
  26. #include <system.h>
  27. #include <error.h>
  28. #include <ems.h>
  29. #include <vm.h>
  30. #include <vmp.h>
  31.  
  32. #if     VMFREE
  33. #define cVmPageQueuedEmsMost 8
  34. #else   /* !VMFREE */
  35. #define cVmPageQueuedEmsMost 1
  36. #endif  /* !VMFREE */
  37.  
  38. extern char       _near _fVmDisableEms = FALSE;
  39. static char       _near _fVmUseEms;
  40. static HEMS       _near hemsVm;
  41. static unsigned   _near _cVmPageHems;
  42. static unsigned   _near _cVmPageQueuedEms;
  43. static unsigned   _near rgiVmPageQueuedEms[cVmPageQueuedEmsMost];
  44.  
  45. #if     VMFREE
  46.  
  47. static unsigned   _near iVmPageEmsNextFree;
  48.  
  49. #endif  /* VMFREE */
  50.  
  51.  
  52. #if     VMPROFILE
  53.  
  54. unsigned long  _near _cVmSwapInEms;
  55. unsigned long  _near _cVmSwapOutEms;
  56.  
  57. #endif  /* VMPROFILE */
  58.  
  59.  
  60. #pragma page()
  61.  
  62. void PRIVATE __VmInitializeEms(void)
  63. {
  64.    VmTracePrintf(("VmInitializeEms\n"));
  65.  
  66. #if     VMPROFILE
  67.       _cVmSwapInEms = _cVmSwapOutEms = 0;
  68. #endif
  69.  
  70.    if (_fVmDisableEms ||
  71.        !__FEmsCheckInstalled() ||
  72.        (__ErrEmsAllocatePages(&hemsVm, 1) != errNoError)
  73.       )
  74.    {
  75.       _fVmUseEms = FALSE;
  76.       return;
  77.    }
  78.  
  79.    _fVmUseEms = TRUE;
  80.    _cVmPageHems = 1;
  81.    _cVmPageQueuedEms = 1;
  82.    rgiVmPageQueuedEms[0] = 0;
  83.  
  84. #if     VMFREE
  85.    iVmPageEmsNextFree = 0xffff;
  86. #endif  /* VMFREE */
  87. }
  88.  
  89.  
  90. #pragma page()
  91.  
  92. void PRIVATE __VmTerminateEms(void)
  93. {
  94.    VmTracePrintf(("VmTerminateEms\n"));
  95.  
  96.    VmProfilePrintf(("VmProfile:\t_cVmSwapInEms = %lu, _cVmSwapOutEms = %lu\n",
  97.             _cVmSwapInEms, _cVmSwapOutEms));
  98.  
  99.    if (_fVmUseEms)
  100.    {
  101.       __ErrEmsDeallocatePages(hemsVm);
  102.  
  103.       _fVmUseEms = FALSE;
  104.    }
  105. }
  106.  
  107.  
  108. #pragma page()
  109.  
  110. void LOCAL __VmFillEmsQueue(void)
  111. {
  112.    VmTracePrintf(("VmFillEmsQueue\n"));
  113.  
  114.    Assert(_fVmUseEms && (_cVmPageQueuedEms == 0));
  115.  
  116. #if     VMFREE
  117.    if (iVmPageEmsNextFree != 0xffff)
  118.    {
  119.       ERR               err;
  120.       move_source_dest  emsmove;
  121.  
  122.       /* Insert first free page in queue. */
  123.  
  124.       /* CONSIDER: Should more than one page be added to queue. */
  125.       /* CONSIDER: I chose not to because a subsequent set of */
  126.       /* CONSIDER: calls to VmFreeEmsPage could result in more */
  127.       /* CONSIDER: EMS calls than occur by not doing so. */
  128.  
  129.       rgiVmPageQueuedEms[_cVmPageQueuedEms++] = iVmPageEmsNextFree;
  130.  
  131.       emsmove.cb          = sizeof(iVmPageEmsNextFree);
  132.       emsmove.fEmsSource  = 1;
  133.       emsmove.hemsSource  = hemsVm;
  134.       emsmove.ibSource    = 0;
  135.       emsmove.iPageSource = iVmPageEmsNextFree;
  136.       emsmove.fEmsDest    = 0;
  137.       emsmove.hemsDest    = 0;
  138.       emsmove.ibDest      = (unsigned) (void _near *) &iVmPageEmsNextFree;
  139.       emsmove.segDest     = (_segment) &iVmPageEmsNextFree;
  140.       err = __ErrEmsMoveMemoryRegion(&emsmove);
  141.       Assert(err == errNoError);
  142.    }
  143.  
  144.    else
  145. #endif  /* VMFREE */
  146.    {
  147.       if (__ErrEmsReallocatePages(hemsVm, _cVmPageHems + 1) != errNoError)
  148.      return;
  149.  
  150.       rgiVmPageQueuedEms[_cVmPageQueuedEms++] = _cVmPageHems++;
  151.  
  152.       VmTracePrintf(("Reallocated EMS Handle.  cPage = %04X.\n", _cVmPageHems));
  153.    }
  154. }
  155.  
  156.  
  157. #pragma page()
  158.  
  159. int PRIVATE __FVmAllocateEmsPage(PPTE ppte, VPVOID vp)
  160. {
  161.    PPTE     ppteBase;
  162.    unsigned iPage;
  163.    PTE      pte;
  164.  
  165.    if (!_fVmUseEms)
  166.       return(FALSE);
  167.  
  168.    Assert(*ppte == 0);
  169.  
  170.    /* Find the base of this 16K range */
  171.  
  172.    ppteBase = ppte - ((vp & 16383UL) / cbVmPage);
  173.  
  174.    /* EMS is only allocated in 16K blocks.  For this allocation to */
  175.    /* succeed, the 16K block containing this page must not contain */
  176.    /* any pages assigned swap storage in XMS or disk. */
  177.  
  178.    for (iPage = 0; iPage < 16384U / cbVmPage; iPage++)
  179.    {
  180.       Assert(!(ppteBase[iPage] & fEmsPte));
  181.  
  182.       if (ppteBase[iPage] & (fXmsPte | fDiskPte))
  183.      return(FALSE);
  184.    }
  185.  
  186.    if (_cVmPageQueuedEms == 0)         /* No Queued pages available. */
  187.       __VmFillEmsQueue();
  188.  
  189.    if (_cVmPageQueuedEms == 0)         /* Queue remains empty. No EMS left. */
  190.       return(FALSE);
  191.  
  192.    pte = (rgiVmPageQueuedEms[--_cVmPageQueuedEms] * 16384UL) | fEmsPte;
  193.  
  194.    vp &= ~(VPVOID) (cbVmPage - 1UL);   /* Virtual address of base of range */
  195.  
  196.    for (iPage = 0; iPage < 16384U / cbVmPage; iPage++)
  197.    {
  198.       HPGD  hpgd;
  199.  
  200.       /* Remember the assigned swap location in the page tables. */
  201.  
  202.       ppteBase[iPage] |= pte;
  203.  
  204.       /* If this page is resident, the swap location must be updated in */
  205.       /* the page descriptor as well or else the page won't be swapped */
  206.       /* out to the correct location. */
  207.  
  208.       if ((ppteBase[iPage] & fAllocatedPte) &&
  209.       ((hpgd = __HpgdSearchCache(vp)) != hpgdNil))
  210.      PpgdOfHpgd(hpgd)->pte |= pte;
  211.  
  212.       pte += cbVmPage;
  213.       vp += cbVmPage;
  214.    }
  215.  
  216.    *ppte |= fAllocatedPte | fUnreferencedPte;
  217.  
  218.    VmTracePrintf(("FVmAllocateEmsPage: SwapLocation = %08lX.\n", *ppte & bitSwapPte));
  219.  
  220.    return(TRUE);
  221. }
  222.  
  223.  
  224. #pragma page()
  225.  
  226. #if     VMFREE
  227.  
  228. void PRIVATE __VmFreeEmsPage(PPTE ppte)
  229. {
  230.    PPTE     ppteBase;
  231.    unsigned iPage;
  232.  
  233.    VmTracePrintf(("VmFreeEmsPage: SwapLocation = %08lX.\n", *ppte & bitSwapPte));
  234.  
  235.    Assert(_fVmUseEms && (*ppte & fEmsPte) && !(*ppte & fAllocatedPte));
  236.  
  237.    /* Find the base of this 16K range */
  238.  
  239.    ppteBase = ppte - ((*ppte & bitSwapPte & 16383UL) / cbVmPage);
  240.  
  241.    /* If any page in this page is allocated, don't free the EMS page. */
  242.  
  243.    for (iPage = 0; iPage < 16384U / cbVmPage; iPage++)
  244.    {
  245.       Assert(ppteBase[iPage] & fEmsPte);
  246.  
  247.       if (ppteBase[iPage] & fAllocatedPte)
  248.      return;
  249.    }
  250.  
  251.    iPage = (unsigned) ((*ppte & bitSwapPte) / 16384UL);
  252.  
  253.    if (_cVmPageQueuedEms < cVmPageQueuedEmsMost)
  254.       rgiVmPageQueuedEms[_cVmPageQueuedEms++] = iPage;
  255.  
  256.    else
  257.    {
  258.       ERR               err;
  259.       move_source_dest  emsmove;
  260.  
  261.       emsmove.cb          = sizeof(iVmPageEmsNextFree);
  262.       emsmove.fEmsDest    = 1;
  263.       emsmove.hemsDest    = hemsVm;
  264.       emsmove.ibDest      = 0;
  265.       emsmove.iPageDest   = iPage;
  266.       emsmove.fEmsSource  = 0;
  267.       emsmove.hemsSource  = 0;
  268.       emsmove.ibSource    = (unsigned) (void _near *) &iVmPageEmsNextFree;
  269.       emsmove.segSource   = (_segment) &iVmPageEmsNextFree;
  270.       err = __ErrEmsMoveMemoryRegion(&emsmove);
  271.       Assert(err == errNoError);
  272.  
  273.       iVmPageEmsNextFree = iPage;
  274.    }
  275.  
  276.    for (iPage = 0; iPage < 16384U / cbVmPage; iPage++)
  277.       ppteBase[iPage] = 0;
  278. }
  279.  
  280. #endif  /* VMFREE */
  281.  
  282.  
  283. #pragma page()
  284.  
  285. int PRIVATE __FVmSwapInEmsPage(PTE pte, HPGD hpgd)
  286. {
  287.    ERR               err;
  288.    move_source_dest  emsmove;
  289.  
  290.    VmTracePrintf(("VmSwapInEmsPage:  pPage = %Fp, SwapLocation = %08lX.\n",
  291.           PPageOfHpgd(hpgd), pte & bitSwapPte));
  292.  
  293. #if     VMPROFILE
  294.    _cVmSwapInEms++;
  295. #endif
  296.  
  297.    Assert(_fVmUseEms && (pte & fEmsPte));
  298.  
  299.    emsmove.cb          = cbVmPage;
  300.    emsmove.fEmsSource  = 1;
  301.    emsmove.hemsSource  = hemsVm;
  302.    emsmove.ibSource    = (unsigned) ((pte & bitSwapPte) & 16383UL);
  303.    emsmove.iPageSource = (unsigned) ((pte & bitSwapPte) / 16384UL);
  304.    emsmove.fEmsDest    = 0;
  305.    emsmove.hemsDest    = 0;
  306.    emsmove.ibDest      = 0;
  307.    emsmove.segDest     = PpgdOfHpgd(hpgd)->segPage;
  308.    err = __ErrEmsMoveMemoryRegion(&emsmove);
  309.  
  310.    Assert(err == errNoError);
  311.    return(err == errNoError);
  312. }
  313.  
  314.  
  315. #pragma page()
  316.  
  317. int PRIVATE __FVmSwapOutEmsPage(PTE pte, HPGD hpgd)
  318. {
  319.    ERR               err;
  320.    move_source_dest  emsmove;
  321.  
  322.    VmTracePrintf(("VmSwapOutEmsPage:  vp = %08lX, pPage = %Fp, SwapLocation = %08lX.\n",
  323.           PpgdOfHpgd(hpgd)->vp, PPageOfHpgd(hpgd), pte & bitSwapPte));
  324.  
  325. #if     VMPROFILE
  326.    _cVmSwapOutEms++;
  327. #endif
  328.  
  329.    Assert(_fVmUseEms && (pte & fEmsPte));
  330.  
  331.    emsmove.cb          = cbVmPage;
  332.    emsmove.fEmsSource  = 0;
  333.    emsmove.hemsSource  = 0;
  334.    emsmove.ibSource    = 0;
  335.    emsmove.segSource   = PpgdOfHpgd(hpgd)->segPage;
  336.    emsmove.fEmsDest    = 1;
  337.    emsmove.hemsDest    = hemsVm;
  338.    emsmove.ibDest      = (unsigned) ((pte & bitSwapPte) & 16383U);
  339.    emsmove.iPageDest   = (unsigned) ((pte & bitSwapPte) / 16384UL);
  340.    err = __ErrEmsMoveMemoryRegion(&emsmove);
  341.  
  342.    Assert(err == errNoError);
  343.    return(err == errNoError);
  344. }
  345.