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

  1. /***
  2. * vmlockm.c -
  3. *
  4. *       Copyright (c) 1989-1992, Microsoft Corporation.  All rights reserved.
  5. *
  6. *Purpose:
  7. *
  8. * PUBLIC Function List
  9. *
  10. *       PVmLockVpCb:
  11. *       This function locks a range of virtual memory and returns a
  12. *       pointer to the first byte of the range.  If the lock fails, the
  13. *       function will return NULL.
  14. *
  15. *       VmUnlockVpCb:
  16. *       This function unlocks a range of virtual memory.  The range
  17. *       must have been locked previously using PVmLockVpCb or PVmLockVp.
  18. *
  19. *******************************************************************************/
  20.  
  21. #pragma title("Virtual Memory Manager")
  22. #pragma subtitle("Locking functions")
  23.  
  24. #include <version.h>
  25. #include <system.h>
  26. #include <error.h>
  27. #include <vmassert.h>
  28. #include <vm.h>
  29. #include <vmp.h>
  30.  
  31. #include <limits.h>
  32. #include <stddef.h>
  33.  
  34. unsigned _near _cVmPage;               /* Count of non-EMS pages allocated */
  35. unsigned _near _timeCur;               /* Current timestamp value */
  36.  
  37. #if     VMPROFILE
  38.  
  39. unsigned long  _near _cVmRefPage;
  40. unsigned long  _near _cVmRefPageEms;
  41. unsigned long  _near _cVmHitPage;
  42. unsigned long  _near _cVmHitPageEms;
  43.  
  44. #endif  /* VMPROFILE */
  45.  
  46.  
  47. #pragma page()
  48.  
  49. PVOID PUBLIC __PVmLockVpCb(VPVOID vp, unsigned long cb)
  50. {
  51.    HPGD     hpgdBase;
  52.    VPVOID   vpPage;
  53.    HPGD     hpgd;
  54.    unsigned cPageNeeded;
  55.    unsigned iPage;
  56.    unsigned cPage;
  57.    PPTE     ppte;
  58.    PTE      pte;
  59.  
  60.    VmTracePrintf(("PVmLockVpCb: vp = %08lX, cb = %08lX.\n", vp, cb));
  61.  
  62.    Assert((vp >= vpptMax) && (vp < vpMax));
  63.    Assert((cb != 0) && (vp + cb > vp));
  64.  
  65.    cPageNeeded = (unsigned) ((cb+IbOfVp(vp)+cbVmPage-1UL) / cbVmPage);
  66.  
  67.    if (cPageNeeded == 1)
  68.       return(__PVmLockVp(vp));
  69.  
  70.    /*
  71.     *   The first step is to determine if any pages in the to be locked
  72.     *   range are already locked.  The first such page found determines
  73.     *   the base page for the range.  Any subsequently found locked pages
  74.     *   must reside in the correct position or else the lock will fail.
  75.     */
  76.  
  77.    hpgdBase = hpgdNil;
  78.    vpPage = VpPageOfVp(vp);
  79.  
  80.    for (iPage = 0; iPage < cPageNeeded; iPage++)
  81.    {
  82.       hpgd = __HpgdSearchCache(vpPage);
  83.  
  84.       if ((hpgd != hpgdNil) && (PpgdOfHpgd(hpgd)->cLock != 0))
  85.       {
  86.      if (PpgdOfHpgd(hpgd)->cLock == cLockPgdMost)
  87.         return(NULL);
  88.  
  89.      if (hpgdBase == hpgdNil)
  90.      {
  91.         hpgdBase = HpgdAdd(hpgd, -(long)iPage);
  92.  
  93.         /* The range determined by this lock must be valid. */
  94.  
  95.         if ((IPageOfHpgd(hpgd) < iPage) ||
  96.  
  97.         ((IPageOfHpgd(hpgdBase) + cPageNeeded) > _cVmPage))
  98.            return(NULL);
  99.      }
  100.  
  101.      else if (hpgdBase != HpgdAdd(hpgd, -(long)iPage))
  102.         return(NULL);
  103.       }
  104.  
  105.       vpPage += cbVmPage;
  106.    }
  107.  
  108.  
  109.    if (hpgdBase != hpgdNil)            /* At least one page is locked */
  110.    {
  111.       hpgd = hpgdBase;
  112.       vpPage = VpPageOfVp(vp);
  113.  
  114.       for (iPage = 0; iPage < cPageNeeded; iPage++)
  115.       {
  116.      /*
  117.       * If there is a discontinuity in the range or the range
  118.       * contains a locked page that is not correct than the
  119.       * lock request will fail.
  120.       */
  121.  
  122.      if (((iPage != 0) &&
  123.           (PpgdOfHpgd(hpgd)->Flags & fDiscontinousPgd)) ||
  124.          ((PpgdOfHpgd(hpgd)->cLock != 0) &&
  125.           (PpgdOfHpgd(hpgd)->vp != vpPage)))
  126.         return(NULL);
  127.  
  128.      vpPage += cbVmPage;
  129.      hpgd = HpgdAdd(hpgd, 1);
  130.       }
  131.    }
  132.  
  133.    else
  134.    {
  135.       /*
  136.        *   The following code finds the lowest range of pages that is
  137.        *   large enough for the block to be loaded.
  138.        */
  139.  
  140.       /* Note:  fDiscontinousPgd is set for the first page (_segVmDos). */
  141.  
  142.       // Gets rid of spurious compiler warnings
  143.       (unsigned)hpgd = HpgdOfIPage0;
  144.       cPage = 0;
  145.  
  146.       for (iPage = 0; iPage < _cVmPage; iPage++)
  147.       {
  148.      if (PpgdOfHpgd(hpgd)->cLock != 0)
  149.         cPage = 0;
  150.  
  151.      else if ((cPage == 0) || (PpgdOfHpgd(hpgd)->Flags & fDiscontinousPgd))
  152.      {
  153.         hpgdBase = hpgd;
  154.         cPage = 1;
  155.      }
  156.  
  157.      else
  158.         cPage++;
  159.  
  160.      if (cPage == cPageNeeded)
  161.         break;
  162.  
  163.      hpgd = HpgdAdd(hpgd, 1);
  164.       }
  165.  
  166.       if (cPage < cPageNeeded)
  167.      return(NULL);
  168.    }
  169.  
  170.  
  171.    hpgd = hpgdBase;
  172.    vpPage = VpPageOfVp(vp);
  173.  
  174.    for (iPage = 0; iPage < cPageNeeded; iPage++)
  175.    {
  176.       HPGD  hpgdT;
  177.  
  178. #if     VMPROFILE
  179.      _cVmRefPage++;
  180. #endif  /* VMPROFILE */
  181.  
  182.       hpgdT = __HpgdSearchCache(vpPage);
  183.  
  184.       if (hpgdT == hpgdNil)            /* Page not resident */
  185.       {
  186.      /* Find where to load this page from */
  187.  
  188.      ppte = __PVmLoadVp(VppteOfVp(vpPage), FALSE);
  189.      Assert(ppte != NULL);
  190.  
  191.      pte = *ppte;
  192.      Assert(pte & fAllocatedPte);
  193.  
  194.      if (pte & fUnreferencedPte)
  195.      {
  196.        __PVmLoadVp(VppteOfVp(vpPage), TRUE); /* Mark page as dirty */
  197.         *ppte &= ~fUnreferencedPte;     
  198.      }
  199.       }
  200.  
  201.       else if (hpgdT != hpgd)          /* Page not in correct location */
  202.       {
  203.      /* CONSIDER: Swapping pages in memory */
  204.  
  205.      /* Flush it from memory to be reloaded */
  206.  
  207.      pte = PpgdOfHpgd(hpgdT)->pte;
  208.  
  209.      if (PpgdOfHpgd(hpgdT)->Flags & fDirtyPgd)
  210.         __VmWriteDirtyPgd(hpgdT);
  211.  
  212.      __VmRemovePgdFromCache(hpgdT);
  213.      PpgdOfHpgd(hpgdT)->Flags &= ~fAllocatedPgd;
  214.      PpgdOfHpgd(hpgdT)->timeRef = 0;
  215.       }
  216.  
  217.       if (hpgdT != hpgd)               /* Must load page */
  218.       {
  219.      unsigned ipgd;
  220.  
  221.      /* Flush the virtual page that is current resident */
  222.  
  223.      if (PpgdOfHpgd(hpgd)->Flags & fDirtyPgd)
  224.         __VmWriteDirtyPgd(hpgd);
  225.  
  226.      /* Remove it from memory */
  227.  
  228.      if (PpgdOfHpgd(hpgd)->Flags & fAllocatedPgd)
  229.         __VmRemovePgdFromCache(hpgd);
  230.  
  231.      else
  232.         PpgdOfHpgd(hpgd)->Flags |= fAllocatedPgd;
  233.  
  234.      __FVmSwapInPage(pte, hpgd);     /* Load the new page into memory */
  235.  
  236.      PpgdOfHpgd(hpgd)->vp  = vpPage;
  237.      PpgdOfHpgd(hpgd)->pte = pte & ~fUnreferencedPte;
  238.      PpgdOfHpgd(hpgd)->hpgdHashNext = _rghpgdHash[ipgd = IpgdHashOfVp(vpPage)];
  239.      _rghpgdHash[ipgd] = hpgd;
  240.       }
  241. #if     VMPROFILE
  242.       else
  243.         _cVmHitPage++;
  244. #endif  /* VMPROFILE */
  245.  
  246.       /* Lock the page */
  247.  
  248.       PpgdOfHpgd(hpgd)->cLock++;
  249.  
  250.       vpPage += cbVmPage;
  251.       hpgd = HpgdAdd(hpgd, 1);
  252.    }
  253.  
  254.    return(PPageOfHpgd(hpgdBase)+IbOfVp(vp));
  255. }
  256.  
  257.  
  258. #pragma page()
  259.  
  260. void PUBLIC __VmUnlockVpCb(VPVOID vp, unsigned long cb, int fDirty)
  261. {
  262.    HPGD     hpgd;
  263.    unsigned cPage;
  264.    unsigned iPage;
  265.  
  266.    VmTracePrintf(("VmUnlockVpCb: vp = %08lX, cb = %08lX, fDirty = %u.\n", vp, cb, fDirty));
  267.  
  268.    Assert((vp >= vpptMax) && (vp < vpMax));
  269.    Assert((cb != 0) && (vp + cb > vp));
  270.  
  271.    hpgd = __HpgdSearchCache(vp);
  272.  
  273.    cPage = (unsigned) ((cb+IbOfVp(vp)+cbVmPage-1) / cbVmPage);
  274.  
  275.    for (iPage = 0; iPage < cPage; iPage++)
  276.    {
  277. #ifdef  VMDEBUG
  278.       HPGD  hpgdBase;
  279.  
  280.       hpgd = __HpgdSearchCache(vp + iPage * cbVmPage);
  281.  
  282.       if (iPage == 0)
  283.      hpgdBase = hpgd;
  284.  
  285.       else
  286.       {
  287.      Assert(hpgd == HpgdAdd(hpgdBase, iPage));
  288.      Assert(!(PpgdOfHpgd(hpgd)->Flags & fDiscontinousPgd));
  289.       }
  290. #endif  /* VMDEBUG */
  291.  
  292.       Assert(PpgdOfHpgd(hpgd)->cLock != 0);
  293.       PpgdOfHpgd(hpgd)->cLock--;
  294.  
  295.       if (++_timeCur == UINT_MAX)
  296.      __VmUpdateTimestamps();
  297.  
  298.       PpgdOfHpgd(hpgd)->timeRef = _timeCur;
  299.  
  300.       if (fDirty)                      /* Mark page as dirty if requested */
  301.      PpgdOfHpgd(hpgd)->Flags |= fDirtyPgd;
  302.  
  303.       hpgd = HpgdAdd(hpgd, 1);
  304.    }
  305. }
  306.