*----------------------------------------------------------- Title[DMesaReclaim.mc..August 29, 1983 4:06 PM..Taft]; *----------------------------------------------------------- ** PILOT ONLY version ** PATCHED to permit coexistence with the new Cedar 5.0 reference-counting microcode. *----------------------------------------------------------- top level; *----------------------------------------------------------- * ReclaimedRef[ref] RETURNS ref or NIL *----------------------------------------------------------- ReclaimedRef: MiscTable[60]; * placement rbase← rbase[rcv], Stack&-1; call[MapRefPiRes]; branch[.+2, r>=0], probe, membase← gcMapPiRce; Stack&+1, IFUNext0; * ref = NIL, do nothing fetch← probe; entry← Md; branch[rrentry, R>=0], entry, T← ResidueField[entry]; branch[rrof, R even], entry; Stack&+1, IFUNext0; * not in table, return ref rrentry: pd← T XOR (residue); branch[.+2, alu=0], T← RefCtField[entry]; Stack&+1, IFUNext0; * not in table, return ref * found as normal entry, so do a deleteref on the entry if not pinned pd← T; branch[.+2, alu#0], pd← T XOR (lastRefCt); branch[cats4]; * OldRefCt = 0 branch[.+2, alu#0], pd← T XOR (rcFinalize); Stack&+1← T - T, branch[rr0n]; branch[.+2, alu#0], entry← (entry) + (reclaimedRefDelta); rcFnzCount← (rcFnzCount) - 1; *RfCntOld = rcFinalize entry← (entry) AND (nrceMask); T← RefCtStkField[entry]; pd← T XOR (becameEmpty); branch[rrempty, alu=0], T← entry; rre1: store← probe, dbuf← T; rr0: Stack&+1← T - (Q← T); call[RefCtDec]; rr0n: Stack← T - T; IFUNext0; rrempty: store← probe, T← dbuf← rceEmpty; Q← T; call[HTCellDec]; branch[rr0n], Stack&+1← T - T; * found an overflow entry in MapPiRce knowrbase[rcv]; rrof: membase← gcStateBR, oiPrev1← T - T; rme[oiCurrent, entry]; rrLoop: oiCurrent← T← (fetch← oiCurrent) + 1; gcTemp← Md, fetch← T; branch[.+2, R>=0], T← ResidueField[gcTemp]; branch[cats1]; pd← T XOR (residue); branch[rr1, alu=0], gcTemp2← Md; branch[rr2, R<0], gcTemp2, T← ResidueField[gcTemp2]; pd← T XOR (residue); branch[.+2, alu=0], T← RefCtField[gcTemp2]; Stack&+1, IFUNext0; * not found, return ref pd← T; branch[.+2, alu#0], pd← T XOR (lastRefCt); branch[cats4]; * OldRefCt = 0 branch[.+2, alu#0], pd← T XOR (rcFinalize); branch[rr0n], Stack&+1← T-T; * found, return NIL, no decrement done branch[.+2, alu#0], gcTemp2← (gcTemp2) + (reclaimedRefDelta); rcFnzCount← (rcFnzCount) - 1; *RfCntOld = rcFinalize gcTemp2← (gcTemp2) AND (nrceMask); T← RefCtStkField[gcTemp2]; pd← T XOR (becameEmpty); branch[rr0x, alu=0], T← gcTemp2; store← oiCurrent, dbuf← T, branch[rr0]; * second entry at end of chain became empty rr0x: call[FreeOi], T← (oiCurrent) - 1; branch[.+2, R<0], T← oiPrev1; membase← gcMapPiRce, T← probe; store← T, T← dbuf← gcTemp, branch[rr0]; * in middle of chain, continue following rr2: oiPrev1← oiCurrent; oiCurrent← Md, branch[rrLoop]; * oiCurrent.rce.res = res rr1: T← RefCtField[gcTemp]; pd← T; branch[.+2, alu#0], pd← T XOR (lastRefCt); branch[cats4]; * OldRefCt = 0 branch[.+2, alu#0], pd← T XOR (rcFinalize); branch[rr0n], Stack&+1← T-T; * found, return NIL branch[.+2, alu#0], gcTemp← (gcTemp) + (reclaimedRefDelta); rcFnzCount← (rcFnzCount) - 1; *RfCntOld = rcFinalize gcTemp← (gcTemp) AND (nrceMask); T← RefCtStkField[gcTemp]; pd← T XOR (becameEmpty); branch[.+2, alu=0], T← (oiCurrent) - 1; store← T, T← dbuf← gcTemp, branch[rr0]; * oiCurrent.rce became empty, Md still has oiCurrent.oe1 gcTemp← Md, branch[rr0x]; *----------------------------------------------------------- * RTSETUP[flag, GCStateHi] RETURNS uVersion * if flag<0 => full setup, refetch all of GCState Info * if flag>=0 => fetch gcstateMask and gcProcNum, store FreeList and nOiFree *----------------------------------------------------------- RTSetup: MiscTable[63], Stack&-3; * placement, make stack empty? T← TIOA&StkP; T← T AND (377C), StkP+2; * restore two args T← Stack&-1, branch[rtsOK, alu=0]; T← 1C; StkP← T; ** stack depth was > 2 => wrong software for this microcode Stack← WrongUVersion, IFUNext0; rtsOK: membase← gcStateBR, * T has gcStateHi Call[DisableNewRCMicrocode]; rbase← rbase[gcTemp], branch[rts2, R>=0], Stack; gcTemp← (BrHi← T) - T; BrLo← gcTemp; * BrLo← 0 fetch← 14S; fetch← 0s, rcFnzCount← Md; fetch← 1s, oiFreeList← Md; fetch← 2s, nOiFree← Md; fetch← 3s, gcStateMask← Md; membase← gcMapPiRce, gcProcNum← Md; gcProcNum← LSH[gcProcNum, 2]; * microcode keeps procNum*4 BrHi← T; T← (mapPiRceOffset); BrLo← T; Stack← UVersion, IFUNext0; * rts2: T← (fetch← 2s) + 1; fetch← T, gcStateMask← Md; gcProcNum← Md; gcProcNum← LSH[gcProcNum, 2]; * microcode keeps procNum*4 store← 14s, dbuf← rcFnzCount; store← 0s, dbuf← oiFreeList; store← 1S, dbuf← nOiFree, IFUNext0; ** need not return UVersion *----------------------------------------------------------- * ResetSTKBits[probe] RETURNS nothing *----------------------------------------------------------- ResetSTKBits: MiscTable[62]; ** placement rbase← rbase[rcv], Stack&-1; rstkLoop: membase← gcMapPiRce, Stack, branch[.+2, R>=0] ; Stack&-1, IFUNext0; * done fetch← Stack; entry← Md; branch[rstkx, R>=0], pd← (entry) AND (emptyRefCtMask); branch[rstkx1, R EVEN], entry; rstkL1: dblbranch[rstkLoop, rstkResched, Reschedule'], Stack← (Stack) + 1; rstkResched: branch[MesaReschedTrap], b← Md; * normal entry, check for becoming absent rstkx: branch[.+2, alu=0], T← (entry) AND (undoStackBit); store← Stack, dbuf← T, branch[rstkL1]; store← Stack, dbuf← rceEmpty; rstkAcct: membase← gcStateBR; call[RstkCellAcct]; branch[rstkL1]; * overflow entry rstkx1: membase← gcStateBr, oiPrev1← T - T; oiPrev0← T - T; rme[oiCurrent, entry]; rstk0: T← (fetch← oiCurrent) + 1; gcTemp← Md; * oiCurrent.rce branch[.+2, R>=0], pd← (gcTemp) AND (emptyRefCtMask); branch[cats1]; branch[rstk1, alu=0], T← gcTemp← (gcTemp) AND (undoStackBit); * oiCurrent.rce # absent oiCurrent← (store← oiCurrent) + 1, dbuf← T; fetch← oiCurrent; * oiCurrent.oe1 gcTemp2← Md; branch[rstkMidChain, R<0], pd← (gcTemp2) AND (emptyRefCtMask); * end of the chain, oiCurrent.oe1 (gcTemp2) is a normal entry branch[.+2, alu=0], T← (gcTemp2) AND (undoStackBit); store← oiCurrent, dbuf← T, branch[rstkL1]; *oiCurrent.oe1 was not empty * oiCurrent.oe1 => empty, move oiCurrent.rce (gcTemp) to oiPrev1 or MapPiRce call[FreeOi], T← (oiCurrent) - 1; dblbranch[rstk2, rstk2x, R<0], oiPrev1, T← oiPrev1; * oiPrev1 = 0 => move gcTemp into MapPiRce rstk2x: membase← gcMapPiRce, T← Stack; * oiPrev # 0 => oiPrev.oe1← gcTemp rstk2: store← T, dbuf← gcTemp, branch[rstkL1]; rstkMidChain: oiPrev0← oiPrev1; oiPrev1← oiCurrent; oiCurrent← Md, branch[rstk0]; * oiCurrent.rce became empty, must check oiCurrent.oe1 rstk1: T← (oiCurrent) + 1; T← (fetch← T) - 1; gcTemp← Md, call[FreeOi]; branch[rstk3, R<0], pd← (gcTemp) AND (emptyRefCtMask); * this is the end of the overflow chain branch[rstk4, alu=0], T← gcTemp← (gcTemp) AND (undoStackBit); * oiCurrent.oe1 did not become empty dblbranch[rstk2, rstk2x, R<0], oiPrev1, T← oiPrev1; * entry in the middle of a chain became empty; oiCurrent has been freed * gcTemp has the link to the next entry rstk3: branch[rstk3x, R<0], T← oiPrev1; * oiPrev1 = 0, => make MapPiRce point to next entry membase← gcMapPiRce, T← gcTemp; * pointer to next on chain store← Stack, dbuf← T; membase← gcStateBR, branch[rstk0], oiCurrent← T; * continue chaining * oiPrev1 # 0, => oiPrev1.oe1← gcTemp rstk3x: store← T, T← dbuf← gcTemp; oiCurrent← T, branch[rstk0]; ** most complicated case - both entries at the end of the chain became empty * if there was only one overflow entry, then MapPiRce← rceEmpty * otherwise, we must look at the entry previous to the previous one (oiPrev0) rstk4: branch[rstk5, R<0], T← (oiPrev1) - 1; * no previous entry, make MapPiRce entry vacant membase← gcMapPiRce; store← Stack, dbuf← rceEmpty; branch[rstkAcct]; * free the Oi at oiPrev1, after fetching its rce, then use oiPrev0 to decide where ** to store oiPrev1.rce rstk5: fetch← T; gcTemp← Md, call[FreeOi]; dblbranch[rstk2, rstk2x, R<0], T← oiPrev0; *----------------------------------------------------------- * ISPIRECLAIMABLE[pi: ProbeIndex] RETURNS[pi: ProbeIndex, npi: CARDINAL] ** code checks for ReSchedule every time around the loop ** stores possibly reclaimable rce's in GCState.rceToReclaim and ** returns the number of rce's it stored for a particular probeIndex ** when npi is returned as 0, the loop is finished ** an rce is a possibly reclaimable REF if rce.rc <= rcFinalize and onStack is not set *----------------------------------------------------------- ISPIRECLAIMABLE: MiscTable[65], * IsPiReclaimable Stack&-1← A0; * preset npi to 0 - used as counter rbase← rbase[rcv]; * placement rcv← rceReclaimOffset; membase← gcMapPiRce, T← pd← Stack; * one extra fetch beyond MapPiRce is ok - that is MapOiOe ipLoop: fetch← T, branch[.+2, alu>=0]; * finished when T < 0 Stack&+1, b← Md, IFUNext0; Stack← T; entry← Md; entry← RefCtStkField[entry], branch[isprn, R>=0]; entry← Md; branch[isprof, R EVEN], entry; * branch if overflow entry T← (Stack) + 1, dblbranch[ipLoop, iplResched, ReSchedule']; *---------------------------- normal entry isprn: branch[ipl2, r Odd], pd← (entry) - (rcFinalize1); * branch if onStack set branch[.+2, alu<0]; * skip if possibly reclaimable T← (Stack) + 1, dblbranch[ipLoop, iplResched, ReSchedule']; membase← GCStateBR, Stack&+1; store← rcv, dbuf← Md; * might be reclaimable Stack← (Stack) + 1, b← Md, IFUNext0; *---------------------------- check for pending interrupts *--------- update Stack (can't before because of page faults) ipL2: dblbranch[ipLoop, iplResched, ReSchedule'], T← (Stack) + 1; *---------------------------- must look at an overflow chain of entries isprof: membase← GCStateBR; * Md has MapPiRce[pi] T← (fetch← entry) + 1; * fetch rce part of overflow entry ispr1: T← gcTemp← Md, fetch← T; branch[.+2, R>=0], gcTemp← RefCtStkField[gcTemp]; branch[cats1]; branch[.+2, r even], pd← (gcTemp) - (rcFinalize1); branch[ispr2], gcTemp← Md; * onStack was set branch[ispr2, alu>=0], gcTemp← Md; **-------------- store entry in GCState.rceToReclaim[rcv] rcv← (store← rcv) + 1, dbuf← T; ispr2: branch[.+2, R>=0], gcTemp← RefCtStkField[gcTemp]; T← (fetch← Md) + 1, branch[ispr1]; * Md has second entry, follow chain ** end of chain, check second entry (gcTemp) branch[ispr3, R odd], pd← (gcTemp) - (rcFinalize1); * onStack was set branch[ispr3x, alu>=0], T← (rcv) - (rceReclaimOffset); rcv← (store← rcv) + 1, dbuf← Md, branch[ispr4]; **-------------- check if anything was stored in GCState.rceToReclaim ispr3: T← (rcv) - (rceReclaimOffset); * test if npi = 0 ispr3x: branch[ispr4x, alu#0], membase← gcMapPiRce; * go looking for more dblBranch[ipLoop, iplResched, ReSchedule'], T← (Stack) + 1; ispr4: T← (rcv) - (rceReclaimOffset); ispr4x: Stack+1← T, b← Md, IFUNext0; ** did find something *---------------------------- allow other processes to run iplResched: b← Md, rbase← rbase[rtemp0]; branch[MesaReschedTrap]; *-------------------------------------------------------- cats1: branch[cats], T← 1C; cats4: branch[cats], T← 4C;