// IfsSequinFeed.bcpl - Sequin feed context - SWAPPABLE // Copyright Xerox Corporation 1979 // Last modified by Wobber, February 9, 1981 2:03 PM get "IfsSequin.decl"; external [ //outgoing procedures SequinFeedCtx; //incoming procedures Allocate; Block; CompletePup; Dequeue; FreePointer; LeafFinish; MoveBlock; SequinFromPBI; SequinReadPBI; SequinRetransmit; SequinUnlockPBI; UnlockSequin; Unqueue; Zero; //incoming statics scb; sysZone; ] //---------------------------------------------------------------------------- let SequinFeedCtx() be //---------------------------------------------------------------------------- [ manifest linkOffset = offset Sequin.outputLink/16; until scb>>SCB.haltFlag do [ let link = scb>>SCB.outputSequinQ.head; while link ne 0 do [ // loop through active output sequin queue [ // empty return queue let pbi = Dequeue(lv scb>>SCB.returnPBIQ); if pbi eq 0 break; let sequin = SequinFromPBI(pbi); SequinUnlockPBI(pbi); sequin>>Sequin.unreturnedPBIs = sequin>>Sequin.unreturnedPBIs - 1; ] repeat let sequin = link - linkOffset; link = sequin>>Sequin.outputLink; if sequin>>Sequin.state eq destroyedState then [ Zero(lv sequin>>Sequin.outputVec, maxOutputVPBIs); sequin>>Sequin.retransmitting = false; FreePointer(lv sequin>>Sequin.retransmitVec); sequin>>Sequin.freeOutputSlot = 0; ] if SendPBIs(sequin) then loop; if sequin>>Sequin.unreturnedPBIs eq 0 then [ Unqueue(lv scb>>SCB.outputSequinQ, sequin+linkOffset); sequin>>Sequin.outputLink = -1; UnlockSequin(sequin); ] ] Block(); ] LeafFinish(); ] //---------------------------------------------------------------------------- and SendPBIs(sequin) = valof //---------------------------------------------------------------------------- [ // Send a pup from the argument sequin and continue to send all which // happen to be in locked down vPages. Return false if nothing to send, // return true otherwise. let doneOne = false; let pbi = 0; [ // Giant repeat loop test sequin>>Sequin.retransmitting; // Retransmit branch...fetch top of retransmit vector... // ...form retransmit vector if necessary. // ifso [ let retransmitVec = sequin>>Sequin.retransmitVec; if retransmitVec eq 0 then [ // Form the retransmit VPBI vector. // Don't start retransmission if outstanding output VPBIs. if sequin>>Sequin.unreturnedPBIs ne 0 then resultis true; retransmitVec = SequinRetransmit(sequin); ] // Test for retransmit completion. // let vecIndex = sequin>>Sequin.retransmitIndex - 1; if vecIndex ls 0 then [ FreePointer(lv sequin>>Sequin.retransmitVec); sequin>>Sequin.retransmitting = false; // Note that a HandleAcks could be done here. loop; // Retry using output branch. ] // Read in the VPBI at the top of the retransmit vector. // pbi = SequinReadPBI(retransmitVec!vecIndex, false, doneOne); if pbi eq 0 break; sequin>>Sequin.retransmitIndex = vecIndex; ] // Output branch....fetch top of output vector. // ifnot [ let vpbiID = sequin>>Sequin.outputVec^0; if vpbiID eq 0 break; let sequence = sequin>>Sequin.sendSequence; pbi = SequinReadPBI(vpbiID, false, doneOne, sequence); if pbi eq 0 break; // We will init vec!maxOutputVPBIs to 0 so that the following works. MoveBlock(lv sequin>>Sequin.outputVec, lv sequin>>Sequin.outputVec^1, maxOutputVPBIs); sequin>>Sequin.freeOutputSlot = sequin>>Sequin.freeOutputSlot - 1; sequin>>Sequin.sendSequence = sequence + 1; sequin>>Sequin.lastSendVPBIID = vpbiID; ] // Branches merge here ... send the pup. let pbiID = lv pbi>>PBI.pup.id; pbiID>>SequinID.allocate = sequin>>Sequin.allocate - sequin>>Sequin.freeInputSlot; pbiID>>SequinID.receiveSequence = sequin>>Sequin.receiveSequence; sequin>>Sequin.unreturnedPBIs = sequin>>Sequin.unreturnedPBIs + 1; CompletePup(pbi, typeLeaf); doneOne = true; ] repeat resultis doneOne ]