home *** CD-ROM | disk | FTP | other *** search
- /***
- * vmlockm.c -
- *
- * Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
- *
- *Purpose:
- *
- * PUBLIC Function List
- *
- * PVmLockVpCb:
- * This function locks a range of virtual memory and returns a
- * pointer to the first byte of the range. If the lock fails, the
- * function will return NULL.
- *
- * VmUnlockVpCb:
- * This function unlocks a range of virtual memory. The range
- * must have been locked previously using PVmLockVpCb or PVmLockVp.
- *
- *******************************************************************************/
-
- #pragma title("Virtual Memory Manager")
- #pragma subtitle("Locking functions")
-
- #include <version.h>
- #include <system.h>
- #include <error.h>
- #include <vmassert.h>
- #include <vm.h>
- #include <vmp.h>
-
- #include <limits.h>
- #include <stddef.h>
-
- unsigned _near _cVmPage; /* Count of non-EMS pages allocated */
- unsigned _near _timeCur; /* Current timestamp value */
-
- #if VMPROFILE
-
- unsigned long _near _cVmRefPage;
- unsigned long _near _cVmRefPageEms;
- unsigned long _near _cVmHitPage;
- unsigned long _near _cVmHitPageEms;
-
- #endif /* VMPROFILE */
-
-
- #pragma page()
-
- PVOID PUBLIC __PVmLockVpCb(VPVOID vp, unsigned long cb)
- {
- HPGD hpgdBase;
- VPVOID vpPage;
- HPGD hpgd;
- unsigned cPageNeeded;
- unsigned iPage;
- unsigned cPage;
- PPTE ppte;
- PTE pte;
-
- VmTracePrintf(("PVmLockVpCb: vp = %08lX, cb = %08lX.\n", vp, cb));
-
- Assert((vp >= vpptMax) && (vp < vpMax));
- Assert((cb != 0) && (vp + cb > vp));
-
- cPageNeeded = (unsigned) ((cb+IbOfVp(vp)+cbVmPage-1UL) / cbVmPage);
-
- if (cPageNeeded == 1)
- return(__PVmLockVp(vp));
-
- /*
- * The first step is to determine if any pages in the to be locked
- * range are already locked. The first such page found determines
- * the base page for the range. Any subsequently found locked pages
- * must reside in the correct position or else the lock will fail.
- */
-
- hpgdBase = hpgdNil;
- vpPage = VpPageOfVp(vp);
-
- for (iPage = 0; iPage < cPageNeeded; iPage++)
- {
- hpgd = __HpgdSearchCache(vpPage);
-
- if ((hpgd != hpgdNil) && (PpgdOfHpgd(hpgd)->cLock != 0))
- {
- if (PpgdOfHpgd(hpgd)->cLock == cLockPgdMost)
- return(NULL);
-
- if (hpgdBase == hpgdNil)
- {
- hpgdBase = HpgdAdd(hpgd, -(long)iPage);
-
- /* The range determined by this lock must be valid. */
-
- if ((IPageOfHpgd(hpgd) < iPage) ||
-
- ((IPageOfHpgd(hpgdBase) + cPageNeeded) > _cVmPage))
- return(NULL);
- }
-
- else if (hpgdBase != HpgdAdd(hpgd, -(long)iPage))
- return(NULL);
- }
-
- vpPage += cbVmPage;
- }
-
-
- if (hpgdBase != hpgdNil) /* At least one page is locked */
- {
- hpgd = hpgdBase;
- vpPage = VpPageOfVp(vp);
-
- for (iPage = 0; iPage < cPageNeeded; iPage++)
- {
- /*
- * If there is a discontinuity in the range or the range
- * contains a locked page that is not correct than the
- * lock request will fail.
- */
-
- if (((iPage != 0) &&
- (PpgdOfHpgd(hpgd)->Flags & fDiscontinousPgd)) ||
- ((PpgdOfHpgd(hpgd)->cLock != 0) &&
- (PpgdOfHpgd(hpgd)->vp != vpPage)))
- return(NULL);
-
- vpPage += cbVmPage;
- hpgd = HpgdAdd(hpgd, 1);
- }
- }
-
- else
- {
- /*
- * The following code finds the lowest range of pages that is
- * large enough for the block to be loaded.
- */
-
- /* Note: fDiscontinousPgd is set for the first page (_segVmDos). */
-
- // Gets rid of spurious compiler warnings
- (unsigned)hpgd = HpgdOfIPage0;
- cPage = 0;
-
- for (iPage = 0; iPage < _cVmPage; iPage++)
- {
- if (PpgdOfHpgd(hpgd)->cLock != 0)
- cPage = 0;
-
- else if ((cPage == 0) || (PpgdOfHpgd(hpgd)->Flags & fDiscontinousPgd))
- {
- hpgdBase = hpgd;
- cPage = 1;
- }
-
- else
- cPage++;
-
- if (cPage == cPageNeeded)
- break;
-
- hpgd = HpgdAdd(hpgd, 1);
- }
-
- if (cPage < cPageNeeded)
- return(NULL);
- }
-
-
- hpgd = hpgdBase;
- vpPage = VpPageOfVp(vp);
-
- for (iPage = 0; iPage < cPageNeeded; iPage++)
- {
- HPGD hpgdT;
-
- #if VMPROFILE
- _cVmRefPage++;
- #endif /* VMPROFILE */
-
- hpgdT = __HpgdSearchCache(vpPage);
-
- if (hpgdT == hpgdNil) /* Page not resident */
- {
- /* Find where to load this page from */
-
- ppte = __PVmLoadVp(VppteOfVp(vpPage), FALSE);
- Assert(ppte != NULL);
-
- pte = *ppte;
- Assert(pte & fAllocatedPte);
-
- if (pte & fUnreferencedPte)
- {
- __PVmLoadVp(VppteOfVp(vpPage), TRUE); /* Mark page as dirty */
- *ppte &= ~fUnreferencedPte;
- }
- }
-
- else if (hpgdT != hpgd) /* Page not in correct location */
- {
- /* CONSIDER: Swapping pages in memory */
-
- /* Flush it from memory to be reloaded */
-
- pte = PpgdOfHpgd(hpgdT)->pte;
-
- if (PpgdOfHpgd(hpgdT)->Flags & fDirtyPgd)
- __VmWriteDirtyPgd(hpgdT);
-
- __VmRemovePgdFromCache(hpgdT);
- PpgdOfHpgd(hpgdT)->Flags &= ~fAllocatedPgd;
- PpgdOfHpgd(hpgdT)->timeRef = 0;
- }
-
- if (hpgdT != hpgd) /* Must load page */
- {
- unsigned ipgd;
-
- /* Flush the virtual page that is current resident */
-
- if (PpgdOfHpgd(hpgd)->Flags & fDirtyPgd)
- __VmWriteDirtyPgd(hpgd);
-
- /* Remove it from memory */
-
- if (PpgdOfHpgd(hpgd)->Flags & fAllocatedPgd)
- __VmRemovePgdFromCache(hpgd);
-
- else
- PpgdOfHpgd(hpgd)->Flags |= fAllocatedPgd;
-
- __FVmSwapInPage(pte, hpgd); /* Load the new page into memory */
-
- PpgdOfHpgd(hpgd)->vp = vpPage;
- PpgdOfHpgd(hpgd)->pte = pte & ~fUnreferencedPte;
- PpgdOfHpgd(hpgd)->hpgdHashNext = _rghpgdHash[ipgd = IpgdHashOfVp(vpPage)];
- _rghpgdHash[ipgd] = hpgd;
- }
- #if VMPROFILE
- else
- _cVmHitPage++;
- #endif /* VMPROFILE */
-
- /* Lock the page */
-
- PpgdOfHpgd(hpgd)->cLock++;
-
- vpPage += cbVmPage;
- hpgd = HpgdAdd(hpgd, 1);
- }
-
- return(PPageOfHpgd(hpgdBase)+IbOfVp(vp));
- }
-
-
- #pragma page()
-
- void PUBLIC __VmUnlockVpCb(VPVOID vp, unsigned long cb, int fDirty)
- {
- HPGD hpgd;
- unsigned cPage;
- unsigned iPage;
-
- VmTracePrintf(("VmUnlockVpCb: vp = %08lX, cb = %08lX, fDirty = %u.\n", vp, cb, fDirty));
-
- Assert((vp >= vpptMax) && (vp < vpMax));
- Assert((cb != 0) && (vp + cb > vp));
-
- hpgd = __HpgdSearchCache(vp);
-
- cPage = (unsigned) ((cb+IbOfVp(vp)+cbVmPage-1) / cbVmPage);
-
- for (iPage = 0; iPage < cPage; iPage++)
- {
- #ifdef VMDEBUG
- HPGD hpgdBase;
-
- hpgd = __HpgdSearchCache(vp + iPage * cbVmPage);
-
- if (iPage == 0)
- hpgdBase = hpgd;
-
- else
- {
- Assert(hpgd == HpgdAdd(hpgdBase, iPage));
- Assert(!(PpgdOfHpgd(hpgd)->Flags & fDiscontinousPgd));
- }
- #endif /* VMDEBUG */
-
- Assert(PpgdOfHpgd(hpgd)->cLock != 0);
- PpgdOfHpgd(hpgd)->cLock--;
-
- if (++_timeCur == UINT_MAX)
- __VmUpdateTimestamps();
-
- PpgdOfHpgd(hpgd)->timeRef = _timeCur;
-
- if (fDirty) /* Mark page as dirty if requested */
- PpgdOfHpgd(hpgd)->Flags |= fDirtyPgd;
-
- hpgd = HpgdAdd(hpgd, 1);
- }
- }
-