// IfsSequinReaper.bcpl - Sequin - SWAPPABLE // Copyright Xerox Corporation 1979, 1980 // Last modified by Wobber, April 1, 1981 10:40 AM get "IfsSequin.decl"; external [ //outgoing procedures SequinReaper; //incoming procedures Block; CloseFH; Dequeue; DoubleIncrement; Free; FreePointer; ScanVPBIPage; SequinDestroy; SetTimer; TimerHasExpired; Umin; Unqueue; //incoming statics haltFlag; leafEnabled; scb; sysZone; ] //---------------------------------------------------------------------------- let SequinReaper() be //---------------------------------------------------------------------------- [ // See if we can reap some VPBIs. if scb>>SCB.activityWord ne 0 then ScanReaperQueues(); // This cleans up dead sequins. let sequin = scb>>SCB.sequinQ.head; until sequin eq 0 do [ let nextSequin = sequin>>Sequin.link; let timerCount = sequin>>Sequin.timerCount; let haltTimerCount = sequin>>Sequin.haltTimerCount; switchon sequin>>Sequin.state into [ case openState: unless timerCount eq 0 do endcase; timerCount = sequin>>Sequin.connTimeout; sequin>>Sequin.state = timedOutState; // fall through case timedOutState: unless sequin>>Sequin.brokenLeaf do endcase; default: timerCount = Umin(brokenConnTimeout, timerCount); endcase; ] test haltTimerCount eq 0 ifso if haltFlag % not leafEnabled then timerCount = 0; ifnot sequin>>Sequin.haltTimerCount = haltTimerCount - 1; test timerCount eq 0 ifso SequinDestroy(sequin); ifnot sequin>>Sequin.timerCount = timerCount - 1; if sequin>>Sequin.state eq destroyedState & sequin>>Sequin.lock eq 0 & sequin>>Sequin.allocateSequence eq sequin>>Sequin.ackedState.reaped & sequin>>Sequin.receiveSequence eq sequin>>Sequin.inputState.reaped then [ // Reap the sequin. [ let fh = sequin>>Sequin.fhQ.head; if fh eq 0 break; CloseFH(sequin, fh); ] repeat Unqueue(lv scb>>SCB.sequinQ, sequin); FreePointer(lv sequin>>Sequin.unam); Free(sysZone, sequin); ] sequin = nextSequin; ] DoubleIncrement(lv scb>>SCB.reaperCycles); ] //---------------------------------------------------------------------------- and ScanReaperQueues() be //---------------------------------------------------------------------------- [ let ancientScan = scb>>SCB.ancientScan; scb>>SCB.ancientScan = false; scb>>SCB.normalScan = ScanVPageQ(lv scb>>SCB.inputAllocInfo, ancientScan) % ScanVPageQ(lv scb>>SCB.outputAllocInfo, ancientScan); if ancientScan then DoubleIncrement(lv scb>>SCB.ancientScans); if scb>>SCB.normalScan then DoubleIncrement(lv scb>>SCB.normalScans); ] //---------------------------------------------------------------------------- and ScanVPageQ(alloc, ancientScan) = valof //---------------------------------------------------------------------------- [ let vPage = nil; let linkPage = nil; let ancientHead = alloc>>AllocInfo.ancientQ.head; let ancientTail = alloc>>AllocInfo.ancientQ.tail; test ancientScan & ancientHead ne 0 ifnot linkPage = (ancientHead ne 0? ancientTail, 0); ifso [ //Scan the ancientQ here. vPage = ancientHead; linkPage = 0; [ let nextVPage = ScanVPBIPage(vPage, alloc, lv linkPage); if vPage eq ancientTail then break; vPage = nextVPage; ] repeat if linkPage eq 0 then alloc>>AllocInfo.ancientQ.head = 0; ] // Return false if nothing to scan on vPageQ. vPage = alloc>>AllocInfo.vPageQ.head; if alloc>>AllocInfo.vPageQ.tail eq 0 % (vPage eq alloc>>AllocInfo.vPageQ.tail & alloc>>AllocInfo.nextVPBI eq 0) then resultis false; // Now scan the vPageQ. alloc>>AllocInfo.vPageQ.head = 0; [ //Loop to scan queue. let nextVPage = ScanVPBIPage(vPage, alloc, lv linkPage); if nextVPage eq 0 break; vPage = nextVPage; ] repeatuntil vPage eq alloc>>AllocInfo.nextVPage alloc>>AllocInfo.vPageQ.head = vPage; resultis true; ]