FOR sl:
LIST
OF YggCamelotSegment.SegPort ← segmentList, sl.rest
UNTIL sl =
NIL
DO
smd: SegmentMetadataList;
mappedAddress: Mach.vmAddressT;
segmentUse: YggCamelotSegment.SegmentUseType;
DIDMapLogicalPage0: CARD32;
NextDIDLogicalPage: CARD32;
page0: LONG POINTER TO YggCamelotSegment.PageZero;
page79: LONG POINTER TO YggCamelotSegment.PageZero;
freePages: INT ← 0;
vmAddressForSegmentAllocMap: YggFileInternal.PTAllocBitmap;
vmAddressForShadowAllocMap: YggFileInternal.PTAllocBitmap;
kernCode: Mach.kernReturnT;
[mappedAddress: mappedAddress, kernCode: kernCode] ← Mach.vmAllocateWithPager[targetTask: Mach.taskSelf[], address: 0, size: YggFile.bytesPerPage, anywhere: TRUE, pagingObject: sl.first.port, offset: 0, raiseSignal: TRUE];
TRUSTED {
page0 ← LOOPHOLE[mappedAddress];
segmentUse ← page0.segmentUse;
DIDMapLogicalPage0 ← page0.DIDMapLogicalPage0;
NextDIDLogicalPage ← page0.NextDIDLogicalPage;
};
IF segmentUse = undefined
THEN {
smd ← LIST[[,sl.first.segment.segmentId, sl.first.port, sl.first.segment.lowSize, undefined, 0, 0, 0, [0], 0, 0, NIL, NIL]];
}
ELSE {
TRUSTED {
IF page0.segmentId # sl.first.segment.segmentId THEN ERROR;
IF segmentUse = systemMetaData OR segmentUse = normalAndSystemMetaData THEN gotMetaData ← TRUE;
[mappedAddress: mappedAddress, kernCode: kernCode] ← Mach.vmAllocateWithPager[targetTask: Mach.taskSelf[], address: 0, size: page0.allocationMapSize*YggFile.bytesPerPage, anywhere: TRUE, pagingObject: sl.first.port, offset: page0.allocationMapStartPage*YggFile.bytesPerPage, raiseSignal: TRUE];
vmAddressForSegmentAllocMap ← LOOPHOLE[mappedAddress];
[mappedAddress: mappedAddress, kernCode: kernCode] ← Mach.vmAllocate[targetTask: Mach.taskSelf[], address: 0, size: page0.allocationMapSize*YggFile.bytesPerPage, anywhere: TRUE, raiseSignal: TRUE];
vmAddressForShadowAllocMap ← LOOPHOLE[mappedAddress];
Copy[from: vmAddressForSegmentAllocMap, nwords: page0.allocationMapSize*YggFile.bytesPerPage/PBasics.bytesPerWord, to: vmAddressForShadowAllocMap];
FOR word:
CARD
IN [0..page0.segmentMaximum/
BITS[YggFileInternal.AllocWord]]
DO
SELECT vmAddressForSegmentAllocMap[word].card
FROM
LAST[CARD32] => {};
0 => freePages ← freePages + 32;
ENDCASE => {
countBitsInByte:
PROC [byte:
BYTE]
RETURNS [cnt:
INT ← 0] ~
CHECKED {
wd: WORD ← 0;
wd ← byte;
UNTIL wd = 0
DO
IF Basics.BITAND[wd, 1] = 0 THEN cnt ← cnt + 1;
wd ← Basics.BITSHIFT[wd, 1];
ENDLOOP;
};
freePages ← countBitsInByte[vmAddressForSegmentAllocMap[word].hh] + countBitsInByte[vmAddressForSegmentAllocMap[word].hl] + countBitsInByte[vmAddressForSegmentAllocMap[word].lh] + countBitsInByte[vmAddressForSegmentAllocMap[word].ll];
};
ENDLOOP;
smd ← LIST[[, sl.first.segment.segmentId, sl.first.port, sl.first.segment.lowSize, segmentUse, page0.segmentLogicalPage0, page0.segmentMaximum - page0.segmentLogicalPage0, freePages, [0], DIDMapLogicalPage0, NextDIDLogicalPage, vmAddressForSegmentAllocMap, vmAddressForShadowAllocMap]];
};
};
kernCode ← Mach.vmDeallocate[targetTask: Mach.taskSelf[], address: LOOPHOLE[page0], size: YggFile.bytesPerPage, raiseSignal: TRUE];
IF SegMetadataList = NIL THEN SegMetadataList ← lastSegmentMetadata ← smd
ELSE {lastSegmentMetadata.rest ← smd; lastSegmentMetadata ← smd};
ENDLOOP;
IF SegMetadataList.rest =
NIL
AND SegMetadataList.first.segmentUse = undefined
THEN {
first time startup for this server: only one segment and it is uninitialized
Must init page 0 and the NextDID page. The DIDMap will self initialize, but we have to init its page 0. The allocaion map is already all zeros, so it is initialized.
firstTimeTID: Camelot.tidT;
outcome: YggEnvironment.Outcome;
status: INT ← -1;
kernCode: Mach.kernReturnT;
page0MappedAddress: Mach.vmAddressT;
nextDIDMappedAddress: Mach.vmAddressT;
didMapPage0MappedAddress: Mach.vmAddressT;
nextDIDLogicalPage: CARD;
didMapLogicalPage0: CARD;
YggLogBasic.EstablishLogFile[];
YggLogBasic.OpenForPut[nextPage: 0, version: 1, nextRecord: [zero, 0, 0]];
firstTime ← TRUE;
firstTimeTID ← YggTransaction.CreateTrans[YggEnvironment.nullTransID];
[newTid: firstTimeTID, kernCode: kernCode] ← Camelot.TABegin[taPort: YggEnvironment.taPort, parentTid: YggEnvironment.nullTransID, transType: ttNvServerBased, raiseSignal: TRUE];
init page 0
[mappedAddress: page0MappedAddress, kernCode: kernCode] ← Mach.vmAllocateWithPager[targetTask: Mach.taskSelf[], address: 0, size: YggFile.bytesPerPage, anywhere: TRUE, pagingObject: SegMetadataList.first.port, offset: 0, raiseSignal: TRUE]; -- map page 0
TRUSTED {
page0: LONG POINTER TO YggCamelotSegment.PageZero;
word32: INT ← -1;
mappedAddress: Mach.vmAddressT;
page0 ← LOOPHOLE[page0MappedAddress];
page0.segmentId ← SegMetadataList.first.segmentId;
page0.segmentUse ← normalAndSystemMetaData;
SegMetadataList.first.segmentUse ← normalAndSystemMetaData;
page0.metadataReplicated ← FALSE;
page0.segmentMaximum ← SegMetadataList.first.lowSize/YggFile.bytesPerPage;
page0.allocationMapSize ← 256;
page0.NextDIDLogicalPage ← nextDIDLogicalPage ← 80;
SegMetadataList.first.NextDIDLogicalPage ← nextDIDLogicalPage;
page0.DIDMapLogicalPage0 ← didMapLogicalPage0 ← page0.NextDIDLogicalPage+1; -- one page for the Next DID
SegMetadataList.first.DIDMapLogicalPage0 ← didMapLogicalPage0;
page0.allocationMapStartPage ← 68+page0.DIDMapLogicalPage0; -- 66 pages (leader + dictionary + 64 + a few) for initial DID map
page0.segmentLogicalPage0 ← page0.allocationMapStartPage+256; -- 256 pages for the allocation map (a megabyte)
SegMetadataList.first.offsetToFirstAllocPage ← page0.segmentLogicalPage0;
SegMetadataList.first.freePages ← SegMetadataList.first.numberOfPages ← page0.segmentMaximum - page0.segmentLogicalPage0;
[mappedAddress: mappedAddress, kernCode: kernCode] ← Mach.vmAllocateWithPager[targetTask: Mach.taskSelf[], address: 0, size: page0.allocationMapSize*YggFile.bytesPerPage, anywhere: TRUE, pagingObject: SegMetadataList.first.port, offset: page0.allocationMapStartPage*YggFile.bytesPerPage, raiseSignal: TRUE];
SegMetadataList.first.vmAddressForSegmentAllocMap ← LOOPHOLE[mappedAddress];
[mappedAddress: mappedAddress, kernCode: kernCode] ← Mach.vmAllocate[targetTask: Mach.taskSelf[], address: 0, size: page0.allocationMapSize*YggFile.bytesPerPage, anywhere: TRUE, raiseSignal: TRUE];
SegMetadataList.first.vmAddressForShadowAllocMap ← LOOPHOLE[mappedAddress];
word32 ← SegMetadataList.first.offsetToFirstAllocPage/32;
FOR w: INT IN [0..word32) DO
SegMetadataList.first.vmAddressForSegmentAllocMap[w].card ← LAST[CARD];
ENDLOOP;
FOR bitNo: INT IN [0..SegMetadataList.first.offsetToFirstAllocPage - 32 * word32) DO
SegMetadataList.first.vmAddressForSegmentAllocMap[word32].bits[bitNo] ← TRUE;
ENDLOOP;
Copy[from: SegMetadataList.first.vmAddressForSegmentAllocMap, nwords: page0.allocationMapSize*YggFile.bytesPerPage/PBasics.bytesPerWord, to: SegMetadataList.first.vmAddressForShadowAllocMap];
};
kernCode ← Camelot.DSPinObject[dsPort: YggEnvironment.dsPort, tid: firstTimeTID, optr: [segmentId: SegMetadataList.first.segmentId, highOffset: 0, lowOffset: 0], size: YggFile.bytesPerPage, raiseSignal: TRUE];
kernCode ← Camelot.DSLogNewValue[dsPort: YggEnvironment.dsPort, tid: firstTimeTID, optr: [segmentId: SegMetadataList.first.segmentId, highOffset: 0, lowOffset: 0], newValue: page0MappedAddress, newValueCnt: YggFile.bytesPerPage, raiseSignal: TRUE];
init NextDID page
[mappedAddress: nextDIDMappedAddress, kernCode: kernCode] ← Mach.vmAllocateWithPager[targetTask: Mach.taskSelf[], address: 0, size: YggFile.bytesPerPage, anywhere: TRUE, pagingObject: SegMetadataList.first.port, offset: YggFile.bytesPerPage*nextDIDLogicalPage, raiseSignal: TRUE]; -- map NextDID page
TRUSTED {
nextDIDPage: LONG POINTER TO YggCamelotSegment.NextDIDPage;
nextDIDPage ← LOOPHOLE[nextDIDMappedAddress];
nextDIDPage.sealDIDMapLeaderPage ← nextDID;
nextDIDPage.didLow ← 0;
nextDIDPage.didHigh ← YggDIDPrivate.HighDIDFirstClient;
};
kernCode ← Camelot.DSPinObject[dsPort: YggEnvironment.dsPort, tid: firstTimeTID, optr: [segmentId: SegMetadataList.first.segmentId, highOffset: 0, lowOffset: YggFile.bytesPerPage*nextDIDLogicalPage], size: YggFile.bytesPerPage, raiseSignal: TRUE];
kernCode ← Camelot.DSLogNewValue[dsPort: YggEnvironment.dsPort, tid: firstTimeTID, optr: [segmentId: SegMetadataList.first.segmentId, highOffset: 0, lowOffset: YggFile.bytesPerPage*nextDIDLogicalPage], newValue: nextDIDMappedAddress, newValueCnt: YggFile.bytesPerPage, raiseSignal: TRUE];
init DIDMap page 0
[mappedAddress: didMapPage0MappedAddress, kernCode: kernCode] ← Mach.vmAllocateWithPager[targetTask: Mach.taskSelf[], address: 0, size: YggFile.bytesPerPage, anywhere: TRUE, pagingObject: SegMetadataList.first.port, offset: YggFile.bytesPerPage*didMapLogicalPage0, raiseSignal: TRUE]; -- map DIDMap page 0
TRUSTED {
didMapPage0: LONG POINTER TO YggCamelotSegment.DIDMapLeaderPage;
didMapPage0 ← LOOPHOLE[didMapPage0MappedAddress];
didMapPage0.sealDIDMapLeaderPage ← didLeader;
didMapPage0.runSize ← 66;
didMapPage0.nextRun ← 0; -- no more runs
};
kernCode ← Camelot.DSPinObject[dsPort: YggEnvironment.dsPort, tid: firstTimeTID, optr: [segmentId: SegMetadataList.first.segmentId, highOffset: 0, lowOffset: YggFile.bytesPerPage*didMapLogicalPage0], size: YggFile.bytesPerPage, raiseSignal: TRUE];
kernCode ← Camelot.DSLogNewValue[dsPort: YggEnvironment.dsPort, tid: firstTimeTID, optr: [segmentId: SegMetadataList.first.segmentId, highOffset: 0, lowOffset: YggFile.bytesPerPage*didMapLogicalPage0], newValue: nextDIDMappedAddress, newValueCnt: YggFile.bytesPerPage, raiseSignal: TRUE];
try to commit
[status: status, kernCode: kernCode] ← Camelot.TAEnd[taPort: YggEnvironment.taPort, tid: firstTimeTID, protocolType: ptTwoPhased, raiseSignal: TRUE];
IF kernCode = Mach.KernSuccess AND status = Camelot.ErSuccess THEN ERROR;
[outcome: outcome] ← YggTransaction.Finish[transID: firstTimeTID, requestedOutcome: commit];
IF outcome # commit THEN ERROR;
kernCode ← Mach.vmDeallocate[targetTask: Mach.taskSelf[], address: page0MappedAddress, size: YggFile.bytesPerPage, raiseSignal: TRUE];
kernCode ← Mach.vmDeallocate[targetTask: Mach.taskSelf[], address: nextDIDMappedAddress, size: YggFile.bytesPerPage, raiseSignal: TRUE];
kernCode ← Mach.vmDeallocate[targetTask: Mach.taskSelf[], address: didMapPage0MappedAddress, size: YggFile.bytesPerPage, raiseSignal: TRUE];
CamelotRecoverable.CamelotRecoveryComplete[];
}