frames: VMSideDoor.FramesDescriptor, stateVectors: VMSideDoor.StateVectorDescriptor] = {
CopyFramesAndStateVectors:
PROC
RETURNS [pagesNeeded:
INT] =
--INLINE-- {
OPEN VMInternal;
base: LONG ORDERED POINTER = LOOPHOLE[VM.AddressForPageNumber[vm.page]];
limit: LONG ORDERED POINTER = base + VM.WordsForPages[vm.count];
p: LONG ORDERED POINTER ← base;
psb: PrincOps.PsbHandle ← PrincOpsUtils.PsbIndexToHandle[PrincOps.StartPsb];
wordsPerSV: CARDINAL = SIZE[PrincOps.StateVector];
svWords: LONG CARDINAL;
PrincOpsUtils.DisableInterrupts[];
THROUGH [0..PrincOps.
PDA.count)
DO
IF PrincOps.
PDA[psb].link.vector
THEN {
IF p + wordsPerSV <= limit
THEN
PrincOpsUtils.LongCOPY[
from: @PrincOps.PDA[PrincOps.PDA[psb].context.state], to: p, nwords: wordsPerSV];
p ← p + wordsPerSV;
};
psb ← psb + SIZE[PrincOps.ProcessStateBlock];
ENDLOOP;
stateVectors ←
DESCRIPTOR[base, Basics.LongDiv[svWords ← p - base, wordsPerSV]];
FOR piece: FrameHeapPiece ← frameHeapPieceList, piece.next
UNTIL piece =
NIL
DO
wordsToCopy: CARDINAL = piece.wordsInUse - SIZE[FrameHeapPieceHeader];
IF p + wordsToCopy <= limit
THEN
PrincOpsUtils.LongCOPY[from: @piece.fsiFrame, to: p, nwords: wordsToCopy];
p ← p + wordsToCopy;
ENDLOOP;
FOR largeFrame: LargeFrame ← largeFrameList, largeFrame.next
UNTIL largeFrame =
NIL
DO
wordsToCopy: CARDINAL = PrincOpsUtils.FrameSize[largeFrame.trueFsi] + SIZE[PrincOps.FrameSizeIndex];
IF p + wordsToCopy <= limit
THEN {
PrincOpsUtils.LongCOPY[from: @largeFrame.fsiFrame, to: p, nwords: wordsToCopy];
p^ ← VMSideDoor.FrameMarker[frame[largeFrame.trueFsi]]; -- overwrite "LargeReturnSlot" with FrameMarker
};
p ← p + wordsToCopy;
ENDLOOP;
PrincOpsUtils.EnableInterrupts[];
frames ← DESCRIPTOR[base + svWords, p - (base + svWords)];
RETURN[VM.PagesForWords[p - base]]
};
DO
pagesNeeded: VM.PageCount;
VM.SwapIn[interval: vm, kill: TRUE, pin: TRUE];
ZeroFreeFrames[];
Process.Yield[];
pagesNeeded ← CopyFramesAndStateVectors[];
VM.Unpin[vm];
IF pagesNeeded <= vm.count THEN EXIT;
VM.Free[vm];
--*stats*-- getFramesRetries ← getFramesRetries.SUCC;
vm ← VM.Allocate[pagesNeeded];