// IfsLeafSwap.bcpl - Leaf - SWAPPABLE // Copyright Xerox Corporation 1979, 1980, 1982 // Last modified April 9, 1982 6:26 PM by Taft get ecBadHandle from "IfsLeafErrors.decl"; get ecReturnFromReturned from "IfsDirs.decl"; get "IfsLeaf.decl"; get "IfsSequin.decl"; external [ //outgoing procedures AnswerSetOp; CheckHandle; LeafCtx; //incoming procedures Allocate; Block; BuddingLeaf; CallersFrame; CloseLeaf; DeleteLeaf; Dequeue; DoNothingLeaf; Enqueue; FalsePredicate; IFSError; InsertBefore; LeafError; LeafFinish; LeafStartup; Min; MoveBlock; OpenLeaf; ParamsLeaf; ReadLeaf; ResetLeaf; ReturnFrom; SequinAllocate; SequinBreak; SequinReadPBI; SequinReleasePBI; SequinPut; SequinUnlockPBI; SequinReaper; SetTimer; TimerHasExpired; TruncateLeaf; UnlockSequin; Unqueue; WriteLeaf; Zero; //incoming statics scb; socLeaf; sysZone; // outgoing statics leafOpLim; ] static leafOpLim = 0; //---------------------------------------------------------------------------- let LeafCtx() be //---------------------------------------------------------------------------- [ manifest linkOffset = offset Sequin.inputLink/16; LeafStartup(); // SequinCtx will check for halt conditions and set this flag. until scb>>SCB.haltFlag do [ let link = scb>>SCB.inputSequinQ.head; while link ne 0 do [ let sequin = link - linkOffset; link = @link; if sequin>>Sequin.state eq destroyedState then [ Zero(lv sequin>>Sequin.inputVec, maxInputVPBIs); sequin>>Sequin.freeInputSlot = 0; ] let vpbiID = sequin>>Sequin.inputVec↑0; if vpbiID ne 0 then [ if Leaf(sequin, vpbiID) then Block(); loop; ] Unqueue(lv scb>>SCB.inputSequinQ, sequin + linkOffset) sequin>>Sequin.inputLink = -1; UnlockSequin(sequin); ] Block() if TimerHasExpired(lv scb>>SCB.reaperTimer) then [ SequinReaper(); // ***Called from here for the stack space. SetTimer(lv scb>>SCB.reaperTimer, reaperInterval); ] ] LeafFinish(); // doesn't return ] //---------------------------------------------------------------------------- and Leaf(sequin, vpbiID) = valof //---------------------------------------------------------------------------- [ let answerPBI = SequinAllocate(sequin); if answerPBI eq 0 resultis false; let sequence = sequin>>Sequin.inputState.current; let pbi = SequinReadPBI(vpbiID, true, false, sequence); let op = pbi>>PBI.pup.dPort.socket↑1; // This word holds op offset or 0 op = (op eq 0)? lv pbi>>PBI.pup.words, op + pbi; // Compute end of pup (word boundary) ... loop until data exhausted let pupLim = lv pbi>>PBI.pup + (pbi>>PBI.pup.length + 1)/2 - checkOvBytes/2; [ leafOpLim = op + (op>>Op.length + 1)/2; let Proc = FalsePredicate; unless op>>Op.length eq 0 % op>>Op.answer % leafOpLim ugr pupLim do [ Proc = selecton (sequin>>Sequin.brokenLeaf? opReset, op>>Op.code) into [ case opRead: ReadLeaf case opWrite: WriteLeaf case opOpen: OpenLeaf case opClose: case opCloseTransaction: CloseLeaf case opReset: ResetLeaf case opDelete: DeleteLeaf case opTruncate: TruncateLeaf case opNoop: DoNothingLeaf case opParams: ParamsLeaf case opTelnet: //TelnetLeaf default: BuddingLeaf ] ] // Break the sequin on a bad format Leaf request, // send an error message if this sequin has a broken Leaf. switchon Proc(sequin, answerPBI, op) into [ //case false: default: SequinBreak(sequin); answerPBI>>PBI.pup.length = 0; case leafOpError: break; case leafOpComplete: op = leafOpLim; if leafOpLim eq pupLim then break; case leafOpPupNotFull: if answerPBI>>PBI.pup.length + 2*lenLargestLeafAnswer le sequin>>Sequin.pupDataBytes + pupOvBytes then loop; case leafOpPupFull: SequinPut(sequin, answerPBI); answerPBI = SequinAllocate(sequin); if answerPBI ne 0 then loop; pbi>>PBI.pup.dPort.socket↑1 = op - pbi; SequinUnlockPBI(pbi); resultis true; ] ] repeat sequin>>Sequin.inputState.current = sequence + 1; SequinReleasePBI(pbi); MoveBlock(lv sequin>>Sequin.inputVec, lv sequin>>Sequin.inputVec↑1, maxInputVPBIs); sequin>>Sequin.freeInputSlot = sequin>>Sequin.freeInputSlot - 1; if answerPBI>>PBI.pup.length le pupOvBytes then [ SequinReleasePBI(answerPBI); resultis false; ] SequinPut(sequin, answerPBI); resultis true; ] //---------------------------------------------------------------------------- and AnswerSetOp(answerPBI, op, length) = valof //---------------------------------------------------------------------------- [ let pbiEvenLength = (answerPBI>>PBI.pup.length - checkOvBytes + 1) & -2 let answer = lv answerPBI>>PBI.pup + pbiEvenLength/2; MoveBlock(answer, op, 2); // move in the request's op and handle answer>>LeafAnswer.op = (@op & opCodeMask) + opAnswerBit + length; answerPBI>>PBI.pup.length = pbiEvenLength + length + checkOvBytes resultis answer; ] //---------------------------------------------------------------------------- and CheckHandle(sequin, answerPBI, op, needLVMD; numargs na) = valof //---------------------------------------------------------------------------- [ let queue = lv sequin>>Sequin.fhQ; let handle = op>>FileRequest.handle; if (handle+#377 & #177400) eq 0 then [ let fh = queue>>Queue.head; until handle eq 0 % fh eq 0 do [ handle = handle + 1; fh = @fh ]; handle = fh; op>>FileRequest.handle = fh; ]; if handle eq 0 % ((na ls 4 % needLVMD) & handle>>FH.lvmd eq 0) % not Unqueue(queue, handle) then [ ReturnFrom(CallersFrame(), LeafError(answerPBI, op, ecBadHandle)); IFSError(ecReturnFromReturned); ] InsertBefore(queue, queue>>Queue.head, handle); if @handle eq 0 then queue>>Queue.tail = handle; resultis handle; ]