*----------------------------------------------------------- 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;