;Alto->8086 small-c compiler rev 2.0 C←CODE SEGMENT $INCLUDE(8086LIB.D) $INCLUDE(rpcpktio.DEC) ASSUME CS:C←CODE, DS:C←DATA ; #include <Context.h> ; extern int /*BOOL*/ ReplyToRFA(); ; extern SignalInitialize(); ; extern int CallFailed; ; extern SendPup(); ; extern WaitUntilSent(); ; extern struct PBI *GetPBI(); ; extern int GetPupHost(); /* returns machine, but can't declare that */ ; extern InitPupLevel1(); ; extern OpenLevel1Socket(/*lclPort, PortProc, queue*/); ; extern RequestRoute(/*net*/); ; extern InitCalendar(/*retries*/); ; extern int Min(); ; extern int/*BOOL*/ MultEq(); ; extern int/*BOOL*/ DoubleEq(); ; extern ReleasePBI(); ; extern int *Dequeue(); ; extern Enqueue(); ; extern InitQueue(); ; extern SetTmr(); ; extern int /*BOOL*/ TmrExp(); ; extern Block(); ; extern CurrentContext(); ; extern int DoubleComp(); ; extern int DoubleInc(); ; extern Move2(); ; extern StartNProcess(); ; extern int *CallersFrame(); ; extern MoveBlock(); ; extern Zero(); ; union Machine myHost; /* net,,host */ ; struct Queue *myCtxQ; ; int *mySoc; ; static struct CallCount callSequence; /* pointer to CallCount generator */ ; static int sent; /* statistics */ ; static int recvd; ; static int retransmitted; ; static int ReceivePktTooLong; /* SIGNAL */ ; static int listenerRunning; /* set false to abort listener */ ; static int signalTimeout; /* debugging: false to avoid transmission timeouts */ ; static int maxTransmissions /* Normally a large constant; reduced during broadcasts. */ ; struct Queue idlerQ; ; static int idlers; /* CARDINAL; -- number idle servers */ ; static int wanting[maxPSBp1]; /* ARRAY PSB.PsbIndex OF BOOLEAN */ ; static struct PBI *waiterPkts[maxPSBp1]; /* ARRAY PSB.PsbIndex OF BufferDefs.PupBuffer */ ; static struct RPCCtx *contexts[maxPSBp1]; /* contexts corresp. to wanting, for debugging. */ ; int broadcastRetransmissions; ; static int minRetransmitPulses; /* Must be set up in initialization code */ ; static int minPingPulses; /* to above values in some reasonable tick */ ; static int maxPingPulses; /* units. */ ; int rpct; ; static Cl(sig, code, sl) ←Cl: ; int sig, code, *sl; PUSH BP MOV BP,SP PUSH CX PUSH BX ; { ; CleanUp(sl); ; BX ← ←sl POP BX PUSH BX CALL ←CleanUp ; }; MOV SP,BP POP BP RET; ; int /* newLength: */ ; PktExchange(inPkt, length, maxLength, state) ←PktExchange: ; struct PBI *inPkt; ; int length, maxLength, state; PUSH BP MOV BP,SP PUSH CX PUSH BX ; { ; struct PBI *reply; ; struct Seal1 s1, *sl; ; struct Queue myQ; ; int myPSB, acked, pingPulses; ; struct RPCCtx *CtxRunning; ; struct Header *header, *recvdHeader; ; struct PktID thisPktID; ; int newLength, pktLength; ; int transmissions, retransmitPulses, pLen; ; int /* BOOL */ isConv; ; struct PBI *rp; ADD SP,0FFD0X ; sl = &s1; s1.data[0] = (int) &reply; reply=0; ;&←s1 LEA BX,[BP-12] ; ←sl ← BX MOV [BP-14],BX ;&←reply LEA BX,[BP-6] ; ←s1+4 ← BX MOV [BP-8],BX MOV WORD PTR [BP-6],0 ; DISABLE(sl); ; BX ← ←sl MOV BX,[BP-14] CALL ←DISABLE ; CtxRunning = CurrentContext(); CALL ←CurrentContext ; ←CtxRunning ← BX MOV [BP-26],BX ; myPSB = CtxRunning->user.myPSB; ; BX ← ←CtxRunning MOV BX,[BP-26] MOV CX,[BX+26] ; ←myPSB ← CX MOV [BP-20],CX ; header = inPkt->pup; ; BX ← ←inPkt MOV BX,[BP+6] MOV CX,[BX+6] ; ←header ← CX MOV [BP-28],CX ; myQ.head = 0; MOV WORD PTR [BP-18],0 ; inPkt->queue = &myQ; ; BX ← ←inPkt MOV BX,[BP+6] ;&←myQ LEA CX,[BP-18] MOV [BX+2],CX ; InitQueue(&myQ); ;&←myQ LEA BX,[BP-18] CALL ←InitQueue ; Enqueue(&myQ, inPkt); ; BX ← ←inPkt MOV BX,[BP+6] ;&←myQ LEA CX,[BP-18] CALL ←Enqueue ; pingPulses = minPingPulses; MOV BX,←minPingPulses ; ←pingPulses ← BX MOV [BP-24],BX ; header->srceHost.w = myHost.w; ; BX ← ←header MOV BX,[BP-28] MOV CX,WORD PTR ←myHost MOV [BX+14],CX ; header->srceSoc.LS = rpcSocket; ; BX ← ←header MOV BX,[BP-28] MOV BYTE PTR [BX+19],01EX ; header->srcePSB = myPSB; ; BX ← ←header MOV BX,[BP-28] ; CX ← ←myPSB MOV CX,[BP-20] MOV [BX+6],CX ; maxTransmissions = defaultMaxTransmissions; MOV ←maxTransmissions,5 ; if (header->destHost.b.host == 0) { ; BX ← ←header MOV BX,[BP-28] MOV AL,[BX+9] OR AL,AL JNZ X1 ; maxTransmissions = broadcastRetransmissions; MOV BX,←broadcastRetransmissions MOV ←maxTransmissions,BX ; header->destSoc.LS = rpcBcstSocket; ; BX ← ←header MOV BX,[BP-28] MOV BYTE PTR [BX+13],025X ; }; X1: ; if (header->pktID.pktSeq == 0) { ; BX ← ←header MOV BX,[BP-28] MOV CX,[BX+30] OR CX,CX JNZ X2 ; switch (state) { ; BX ← ←state MOV BX,[BP-4] JR X3 ; case calling: header->type.fields = typeCall; break; X5: ; BX ← ←header MOV BX,[BP-28] MOV BYTE PTR [BX+3],060X JR X4 ; case authReq: header->type.fields = typeRFA; break; X6: ; BX ← ←header MOV BX,[BP-28] MOV BYTE PTR [BX+3],064X JR X4 ; default: SIGNAL(ERROR, 0); X7: XOR BX,BX MOV CX,2 CALL ←SIGNAL ; }; /* endCall */ JR X4 X3: MOV AL,BH OR AL,AL JNZ X7 MOV AL,BL CMP AL,2 JZ X5 CMP AL,4 JZ X6 JR X7 X4: ; NewCallNumber(&header->pktID.callCt); ; BX ← ←header MOV BX,[BP-28] ADD BX,01AX CALL ←NewCallNumber ; header->pktID.pktSeq=swapped1; ; BX ← ←header MOV BX,[BP-28] MOV WORD PTR [BX+30],0100X ; }; ; else { JR X8 X2: ; switch (state) { ; BX ← ←state MOV BX,[BP-4] JR X9 ; case endCall: header->type.fields = typeData; break; X11: ; BX ← ←header MOV BX,[BP-28] MOV BYTE PTR [BX+3],061X JR X10 ; case calling: /* Subsequent call packets -- we don't do it. */ X12: ; default: SIGNAL(ERROR, 0); X13: XOR BX,BX MOV CX,2 CALL ←SIGNAL ; }; /* authReq */ JR X10 X9: MOV AL,BH OR AL,AL JNZ X13 MOV AL,BL CMP AL,3 JZ X11 CMP AL,2 JZ X12 JR X13 X10: ; header->pktID.pktSeq += swapped1; ; BX ← ←header MOV BX,[BP-28] ADD WORD PTR [BX+30],0100X ; }; X8: ; acked=false; MOV WORD PTR [BP-22],0 ; MoveBlock(&thisPktID, &header->pktID, lenPktID); ;&←thisPktID LEA BX,[BP-38] PUSH BX ; BX ← ←header MOV BX,[BP-28] ADD BX,018X PUSH BX MOV BX,4 POP CX CALL ←MoveBlock POP DX ; ENABLE(UNWIND, &Cl, sl); MOV BX,1 PUSH BX ; BX ← ←sl MOV BX,[BP-14] MOV CX,OFFSET ←Cl CALL ←ENABLE POP DX ; for (;;) { /* loop for Pings */ X14: ; transmissions = 0; MOV WORD PTR [BP-44],0 ; retransmitPulses=minRetransmitPulses; MOV BX,←minRetransmitPulses ; ←retransmitPulses ← BX MOV [BP-46],BX ; if (inPkt->convHandle != unencrypted) ; BX ← ←inPkt MOV BX,[BP+6] MOV CX,[BX+4] OR CX,CX JZ X16 ; pLen = EncryptPkt(inPkt, length); ; BX ← ←length MOV BX,[BP+4] ; CX ← ←inPkt MOV CX,[BP+6] CALL ←EncryptPkt ; ←pLen ← BX MOV [BP-48],BX ; else pLen = (length + pktLengthOverhead); JR X17 X16: ; BX ← ←length MOV BX,[BP+4] ADD BX,015X ; ←pLen ← BX MOV [BP-48],BX X17: ; header->length = swab(pLen<< 1); ; BX ← ←pLen MOV BX,[BP-48] SAL BX CALL ←swab MOV CX,BX ; BX ← ←header MOV BX,[BP-28] MOV [BX],CX ; for (;;) { /* loop for ReTransmissions */ X18: ; SetWanting(myPSB); ; BX ← ←myPSB MOV BX,[BP-20] CALL ←SetWanting ; WaitUntilSent(inPkt); /* make sure transmission's complete??? */ ; BX ← ←inPkt MOV BX,[BP+6] CALL ←WaitUntilSent ; SendPup(inPkt); ; BX ← ←inPkt MOV BX,[BP+6] CALL ←SendPup ; sent += 1; INC ←sent ; for (;;) { /* loop for Receiving each incoming packet (including garbage) */ X20: ; SetWanting(myPSB); ; BX ← ←myPSB MOV BX,[BP-20] CALL ←SetWanting ; reply = MyReceive(myPSB, ((acked)? pingPulses: retransmitPulses)); ; BX ← ←acked MOV BX,[BP-22] OR BX,BX JZ X22 ; BX ← ←pingPulses MOV BX,[BP-24] JR X23 X22: ; BX ← ←retransmitPulses MOV BX,[BP-46] X23: ; CX ← ←myPSB MOV CX,[BP-20] CALL ←MyReceive ; ←reply ← BX MOV [BP-6],BX ; if (reply == 0) ; BX ← ←reply MOV BX,[BP-6] OR BX,BX JNZ X24 ; if (acked) goto Ping; ; BX ← ←acked MOV BX,[BP-22] OR BX,BX JZ X25 JMP ←Ping ; else { header->type.fields |= ackField; goto Retransmit; }; X25: ; BX ← ←header MOV BX,[BP-28] OR BYTE PTR [BX+3],8 JMP ←Retransmit X24: ; recvdHeader = reply->pup; ; BX ← ←reply MOV BX,[BP-6] MOV CX,[BX+6] ; ←recvdHeader ← CX MOV [BP-30],CX ; if ((recvdHeader->type.fields&classField) == rfa) { ; BX ← ←recvdHeader MOV BX,[BP-30] MOV AL,[BX+3] AND AL,7 CMP AL,4 JNZ X26 ; rp=reply; ; BX ← ←reply MOV BX,[BP-6] ; ←rp ← BX POP DX PUSH BX ; reply=0; MOV WORD PTR [BP-6],0 ; if (ReplyToRFA(rp, header /*encrypted*/, ; &thisPktID /*clear*/, inPkt->convHandle)) acked=acked; ; BX ← ←rp POP BX PUSH BX PUSH BX ; BX ← ←header MOV BX,[BP-28] PUSH BX ; BX ← ←inPkt MOV BX,[BP+6] MOV CX,[BX+4] MOV BX,CX ;&←thisPktID LEA CX,[BP-38] CALL ←ReplyToRFA ADD SP,4 OR BX,BX JZ X27 ; BX ← ←acked MOV BX,[BP-22] ; ←acked ← BX MOV [BP-22],BX X27: ; continue; }; JR X20 X26: ; isConv = swab(recvdHeader->srceHost.w ↑ header->destHost.w); /* comparison results */ ; BX ← ←recvdHeader MOV BX,[BP-30] MOV CX,[BX+14] ; BX ← ←header MOV BX,[BP-28] MOV AX,[BX+8] XOR CX,AX MOV BX,CX CALL ←swab ; ←isConv ← BX MOV [BP-50],BX ; isConv = (isConv==0 || isConv==recvdHeader->srceHost.b.host); /* equal or near-equal */ ; BX ← ←isConv MOV BX,[BP-50] OR BX,BX JZ X29 ; BX ← ←recvdHeader MOV BX,[BP-30] MOV AL,[BX+15] XOR AH,AH ; BX ← ←isConv MOV BX,[BP-50] CMP BX,AX X29: X28: JNZ X30 MOV BX,1 JR X31 X30: XOR BX,BX X31: ; ←isConv ← BX MOV [BP-50],BX ; isConv = (DoubleEq(&recvdHeader->conv,&header->conv) && isConv); /*our conv*/ ; BX ← ←recvdHeader MOV BX,[BP-30] ADD BX,014X ; CX ← ←header MOV CX,[BP-28] ADD CX,014X XCHG BX,CX CALL ←DoubleEq OR BX,BX JZ X32 ; BX ← ←isConv MOV BX,[BP-50] OR BX,BX X32: JZ X33 MOV BX,1 JR X34 X33: XOR BX,BX X34: ; ←isConv ← BX MOV [BP-50],BX ; if ((inPkt->convHandle != unencrypted) && isConv) { ; BX ← ←inPkt MOV BX,[BP+6] MOV CX,[BX+4] OR CX,CX JZ X36 ; BX ← ←isConv MOV BX,[BP-50] OR BX,BX X36: JZ X35 ; DecryptPkt(recvdHeader, inPkt->convHandle, &newLength); ; BX ← ←recvdHeader MOV BX,[BP-30] PUSH BX ; BX ← ←inPkt MOV BX,[BP+6] MOV CX,[BX+4] ;&←newLength LEA BX,[BP-40] CALL ←DecryptPkt POP DX ; pktLength = newLength + pktLengthOverhead; } ; BX ← ←newLength MOV BX,[BP-40] ADD BX,015X ; ←pktLength ← BX MOV [BP-42],BX ; else { JR X37 X35: ; pktLength = (swab(recvdHeader->length)) >> 1; ; DI ← ←recvdHeader MOV DI,[BP-30] MOV BX,[DI] CALL ←swab SHR BX ; ←pktLength ← BX MOV [BP-42],BX ; newLength = pktLength - pktLengthOverhead; }; ; BX ← ←pktLength MOV BX,[BP-42] ADD BX,0FFEBX ; ←newLength ← BX MOV [BP-40],BX X37: ; if (isConv && (recvdHeader->pktID.activity == thisPktID.activity)) ; BX ← ←isConv MOV BX,[BP-50] OR BX,BX JZ X39 ; BX ← ←recvdHeader MOV BX,[BP-30] MOV CX,[BX+24] ; BX ← ←thisPktID MOV BX,[BP-38] CMP CX,BX JNZ X39 MOV AL,1 JR X40 X39: XOR AL,AL X40: OR AL,AL JZ X38 ; if (DoubleEq(&recvdHeader->pktID.callCt, &thisPktID.callCt)) ; BX ← ←recvdHeader MOV BX,[BP-30] ADD BX,01AX PUSH BX ;&←thisPktID LEA BX,[BP-36] POP CX CALL ←DoubleEq OR BX,BX JZ X41 ; if (recvdHeader->pktID.pktSeq == swapped1+thisPktID.pktSeq) { ; BX ← ←recvdHeader MOV BX,[BP-30] MOV CX,[BX+30] ; BX ← ←thisPktID+6 MOV BX,[BP-32] ADD BX,0100X CMP CX,BX JNZ X42 ; if (state == endCall) /* he's not allowed to generate that pktSeq! */ ; BX ← ←state MOV BX,[BP-4] CMP BX,3 JNZ X43 ; SIGNAL(CallFailed, runtimeProtocol); MOV BX,0FX MOV CX,←CallFailed CALL ←SIGNAL X43: ; switch (recvdHeader->type.fields&classField) { ; BX ← ←recvdHeader MOV BX,[BP-30] MOV AL,[BX+3] AND AL,7 JR X44 ; case xtraData: break; X46: JR X45 ; case ack: { X47: ; acked = true; MOV WORD PTR [BP-22],0FFFFX ; CleanUp(sl); ; BX ← ←sl MOV BX,[BP-14] CALL ←CleanUp ; continue; }; JMP X20 ; default: SIGNAL(CallFailed, runtimeProtocol); }; /* call, rfa */ X48: MOV BX,0FX MOV CX,←CallFailed CALL ←SIGNAL JR X45 X44: CMP AL,1 JZ X46 CMP AL,2 JZ X47 JR X48 X45: ; goto Done; }; JMP ←Done ; else if (recvdHeader->pktID.pktSeq == thisPktID.pktSeq) { X42: ; BX ← ←recvdHeader MOV BX,[BP-30] MOV CX,[BX+30] ; BX ← ←thisPktID+6 MOV BX,[BP-32] CMP CX,BX JR $+5 X38: JMP X50 JNZ X49 ; switch (recvdHeader->type.fields&classField) { ; BX ← ←recvdHeader MOV BX,[BP-30] MOV AL,[BX+3] AND AL,7 JR X51 ; case ack: { /* acknowledgement of our packet -- */ X53: ; if ((header->type.fields&classField) == call) header->destPSB = recvdHeader->srcePSB; ; BX ← ←header MOV BX,[BP-28] JR $+5 X41: JMP X55 MOV AL,[BX+3] AND AL,7 OR AL,AL JNZ X54 ; BX ← ←header MOV BX,[BP-28] ; CX ← ←recvdHeader MOV CX,[BP-30] MOV DI,CX MOV CX,[DI+6] MOV [BX+4],CX X54: ; acked = true; MOV WORD PTR [BP-22],0FFFFX ; if (state == endCall) { CleanUp(sl); goto Done; }; ; BX ← ←state MOV BX,[BP-4] CMP BX,3 JNZ X56 ; BX ← ←sl MOV BX,[BP-14] CALL ←CleanUp JMP ←Done ; else /* state = calling or authReq -- */ X56: ; CleanUp(sl); ; BX ← ←sl MOV BX,[BP-14] CALL ←CleanUp ; break; }; JR X52 ; case xtraData: case call: /* retransmission of his packet; X57: X58: ; default: SIGNAL(CallFailed, runtimeProtocol); }; X59: MOV BX,0FX MOV CX,←CallFailed CALL ←SIGNAL JR X52 X51: CMP AL,2 JZ X53 CMP AL,1 JZ X57 CMP AL,0 JZ X58 JR X59 X52: ; }; ; else if (recvdHeader->pktID.pktSeq < thisPktID.pktSeq) CleanUp(sl); /* no need to ack it */ JR X60 X49: ; BX ← ←recvdHeader MOV BX,[BP-30] MOV CX,[BX+30] ; BX ← ←thisPktID+6 MOV BX,[BP-32] CMP CX,BX JGE X61 ; BX ← ←sl MOV BX,[BP-14] CALL ←CleanUp ; else SIGNAL(CallFailed, runtimeProtocol); JR X62 X61: MOV BX,0FX MOV CX,←CallFailed CALL ←SIGNAL X62: X60: ; else JR X63 X55: ; if (((DoubleComp(&recvdHeader->pktID.callCt, &thisPktID.callCt)+1) > 1) && ; (state == endCall)) { ; BX ← ←recvdHeader MOV BX,[BP-30] ADD BX,01AX PUSH BX ;&←thisPktID LEA BX,[BP-36] POP CX CALL ←DoubleComp INC BX CMP BX,1 JLE X65 ; BX ← ←state MOV BX,[BP-4] CMP BX,3 JNZ X65 MOV AL,1 JR X66 X65: XOR AL,AL X66: OR AL,AL JZ X64 ; if ((recvdHeader->type.fields&classField) != call) SIGNAL(CallFailed, runtimeProtocol); ; BX ← ←recvdHeader MOV BX,[BP-30] MOV AL,[BX+3] AND AL,7 OR AL,AL JZ X67 MOV BX,0FX MOV CX,←CallFailed CALL ←SIGNAL X67: ; goto Done; }; JMP ←Done ; else { /* wrong call; let someone else do it -- */ X64: ; recvdHeader->destPSB = nullPSB; EnqueueAgain(reply); reply=0; }; ; BX ← ←recvdHeader MOV BX,[BP-30] MOV WORD PTR [BX+4],0 ; BX ← ←reply MOV BX,[BP-6] CALL ←EnqueueAgain MOV WORD PTR [BP-6],0 X63: ; else { recvdHeader->destPSB = nullPSB; EnqueueAgain(reply); reply=0; }; JR X68 X50: ; BX ← ←recvdHeader MOV BX,[BP-30] MOV WORD PTR [BX+4],0 ; BX ← ←reply MOV BX,[BP-6] CALL ←EnqueueAgain MOV WORD PTR [BP-6],0 X68: ; }; /* endloop for each incoming packet */ JMP X20 X21: ←Retransmit: ; Retransmit: ; transmissions += 1; INC WORD PTR [BP-44] ; if ((transmissions == maxTransmissions) || state == authReq) { MOV BX,←maxTransmissions ; CX ← ←transmissions MOV CX,[BP-44] CMP CX,BX JZ X71 ; BX ← ←state MOV BX,[BP-4] CMP BX,4 X71: X70: JNZ X69 ; if (signalTimeout) SIGNAL(CallFailed, timeout); MOV BX,←signalTimeout OR BX,BX JZ X72 MOV BX,0DX MOV CX,←CallFailed CALL ←SIGNAL X72: ; transmissions = 0; retransmitPulses = minRetransmitPulses*maxTransmissions; MOV WORD PTR [BP-44],0 MOV AX,←minRetransmitPulses MOV BX,←maxTransmissions IMUL AX,BX ; ←retransmitPulses ← AX MOV [BP-46],AX ; }; X69: ; retransmitted += 1; INC ←retransmitted ; retransmitPulses += minRetransmitPulses; MOV BX,←minRetransmitPulses ADD [BP-46],BX ; Block(); CALL ←Block ; continue; JMP X18 ; }; /* end loop for retransmissions */ X19: ←Ping: ; Ping: ; header->type.fields = typePing; ; BX ← ←header MOV BX,[BP-28] MOV BYTE PTR [BX+3],06AX ; length=0; MOV WORD PTR [BP+4],0 ; MoveBlock(&header->pktID, &thisPktID, lenPktID); ; BX ← ←header MOV BX,[BP-28] ADD BX,018X PUSH BX MOV BX,4 ;&←thisPktID LEA CX,[BP-38] CALL ←MoveBlock POP DX ; acked=false; MOV WORD PTR [BP-22],0 ; pingPulses = pingPulses*2; ; BX ← ←pingPulses MOV BX,[BP-24] SAL BX ; ←pingPulses ← BX MOV [BP-24],BX ; if ( (pingPulses<0) || (pingPulses>maxPingPulses) ) pingPulses = maxPingPulses; ; BX ← ←pingPulses MOV BX,[BP-24] CMP BX,0 JL X75 MOV BX,←maxPingPulses ; CX ← ←pingPulses MOV CX,[BP-24] CMP CX,BX JLE X74 X75: MOV AL,1 JR X76 X74: XOR AL,AL X76: OR AL,AL JZ X73 MOV BX,←maxPingPulses ; ←pingPulses ← BX MOV [BP-24],BX X73: ; Block(); CALL ←Block ; }; /* end loop for pings -- */ JMP X14 X15: ←Done: ; Done: { ; ClearWanting(myPSB); ; BX ← ←myPSB MOV BX,[BP-20] CALL ←ClearWanting ; if (reply == 0) { ; BX ← ←reply MOV BX,[BP-6] OR BX,BX JNZ X77 ; MoveBlock(&header->pktID, &thisPktID, lenPktID); ; BX ← ←header MOV BX,[BP-28] ADD BX,018X PUSH BX MOV BX,4 ;&←thisPktID LEA CX,[BP-38] CALL ←MoveBlock POP DX ; return -1; MOV BX,0FFFFX MOV SP,BP POP BP RET; ; }; X77: ; if ((recvdHeader->callSpec.outcome == signal) || ; (newLength > maxLength)) SIGNAL(CallFailed, runtimeProtocol); ; BX ← ←recvdHeader MOV BX,[BP-30] MOV CX,[BX+32] MOV BX,CX CMP BX,2 JZ X80 ; BX ← ←maxLength MOV BX,[BP-2] ; CX ← ←newLength MOV CX,[BP-40] CMP CX,BX JLE X79 X80: MOV AL,1 JR X81 X79: XOR AL,AL X81: OR AL,AL JZ X78 MOV BX,0FX MOV CX,←CallFailed CALL ←SIGNAL X78: ; MoveBlock(header, recvdHeader, pktLength); ; BX ← ←header MOV BX,[BP-28] PUSH BX ; BX ← ←pktLength MOV BX,[BP-42] ; CX ← ←recvdHeader MOV CX,[BP-30] CALL ←MoveBlock POP DX ; CleanUp(sl); ; BX ← ←sl MOV BX,[BP-14] CALL ←CleanUp ; Block(); CALL ←Block ; return newLength; ; BX ← ←newLength MOV BX,[BP-40] MOV SP,BP POP BP RET; ; }; ; SIGNAL(ERROR, 0); XOR BX,BX MOV CX,2 CALL ←SIGNAL ; }; MOV SP,BP POP BP RET; ; static CleanUp(sl) ←CleanUp: ; struct Seal1 *sl; PUSH BP MOV BP,SP PUSH BX ; { /* UNWIND proc */ ; int myPSB, *lvReply; ; struct RPCCtx *CtxRunning; ADD SP,0FFFAX ; CtxRunning = CurrentContext(); CALL ←CurrentContext ; ←CtxRunning ← BX POP DX PUSH BX ; myPSB = CtxRunning->user.myPSB; ; BX ← ←CtxRunning POP BX PUSH BX MOV CX,[BX+26] ; ←myPSB ← CX MOV [BP-4],CX ; ClearWanting(myPSB); ; BX ← ←myPSB MOV BX,[BP-4] CALL ←ClearWanting ; lvReply = (int *) sl->data[0]; ; BX ← ←sl MOV BX,[BP-2] ADD BX,4 MOV CX,[BX] ; ←lvReply ← CX MOV [BP-6],CX ; if (*lvReply != 0) ReleasePBI(*lvReply); ; DI ← ←lvReply MOV DI,[BP-6] MOV BX,[DI] OR BX,BX JZ X82 ; DI ← ←lvReply MOV DI,[BP-6] MOV BX,[DI] CALL ←ReleasePBI X82: ; *lvReply=0; ; BX ← ←lvReply MOV BX,[BP-6] MOV WORD PTR [BX],0 ; }; MOV SP,BP POP BP RET; ; static int NewCallNumber(lvResult) ←NewCallNumber: ; struct CallCount *lvResult; PUSH BP MOV BP,SP PUSH BX ; { ; DoubleInc(&callSequence, 1); MOV BX,1 LEA CX,←callSequence CALL ←DoubleInc ; Move2(lvResult, &callSequence); LEA BX,←callSequence ; CX ← ←lvResult POP CX PUSH CX CALL ←Move2 ; }; MOV SP,BP POP BP RET; ; static SetWanting(myPSB) ←SetWanting: ; int myPSB; PUSH BP MOV BP,SP PUSH BX ; { ; wanting[myPSB]=true; ; BX ← ←myPSB POP BX PUSH BX LEA CX,←wanting SAL BX ADD BX,CX MOV WORD PTR [BX],0FFFFX ; }; MOV SP,BP POP BP RET; ; static ClearWanting(myPSB) ←ClearWanting: ; int myPSB; PUSH BP MOV BP,SP PUSH BX ; { ; wanting[myPSB]=false; ; BX ← ←myPSB POP BX PUSH BX LEA CX,←wanting SAL BX ADD BX,CX MOV WORD PTR [BX],0 ; if (waiterPkts[myPSB]) { ; BX ← ←myPSB POP BX PUSH BX LEA CX,←waiterPkts SAL BX ADD BX,CX MOV CX,[BX] OR CX,CX JZ X83 ; ReleasePBI(waiterPkts[myPSB]); ; BX ← ←myPSB POP BX PUSH BX LEA CX,←waiterPkts SAL BX ADD BX,CX MOV CX,[BX] MOV BX,CX CALL ←ReleasePBI ; waiterPkts[myPSB] = 0; ; BX ← ←myPSB POP BX PUSH BX LEA CX,←waiterPkts SAL BX ADD BX,CX MOV WORD PTR [BX],0 ; }; X83: ; }; MOV SP,BP POP BP RET; ; static struct PBI *MyReceive(myPSB, waitTime) ←MyReceive: ; int myPSB, waitTime; PUSH BP MOV BP,SP PUSH CX PUSH BX ; { ; int timer; ; struct PBI *recvd; ADD SP,0FFFCX ; timer=0; MOV WORD PTR [BP-6],0 ; SetTmr(waitTime, &timer); /* sentTime is implicit, if SetTimer called quickly enuf. */ ;&←timer LEA BX,[BP-6] ; CX ← ←waitTime MOV CX,[BP-4] CALL ←SetTmr ; for (;;) { X84: ; recvd = waiterPkts[myPSB]; ; BX ← ←myPSB MOV BX,[BP-2] LEA CX,←waiterPkts SAL BX ADD BX,CX MOV CX,[BX] ; ←recvd ← CX POP DX PUSH CX ; if (recvd) { ; BX ← ←recvd POP BX PUSH BX OR BX,BX JZ X86 ; waiterPkts[myPSB] = 0; ; BX ← ←myPSB MOV BX,[BP-2] LEA CX,←waiterPkts SAL BX ADD BX,CX MOV WORD PTR [BX],0 ; return recvd; ; BX ← ←recvd POP BX PUSH BX MOV SP,BP POP BP RET; ; }; X86: ; if (TmrExp(&timer)) return 0; ;&←timer LEA BX,[BP-6] CALL ←TmrExp OR BX,BX JZ X87 XOR BX,BX MOV SP,BP POP BP RET; X87: ; Block(); CALL ←Block ; }; JR X84 X85: ; }; MOV SP,BP POP BP RET; ; IdleReceive(pkt, maxLength) ←IdleReceive: ; struct PBI *pkt; ; int maxLength; PUSH BP MOV BP,SP PUSH CX PUSH BX ; { ; struct PBI *b; ; struct Header *recvdHeader; ; int pktLength; ADD SP,0FFFAX ; idlers += 1; INC ←idlers ; while (idlerQ.head == 0) Block(); /* WAIT idlerCond */ X88: MOV BX,WORD PTR ←idlerQ OR BX,BX JNZ X89 CALL ←Block JR X88 X89: ; b = (struct PBI *) Dequeue(&idlerQ); LEA BX,←idlerQ CALL ←Dequeue ; ←b ← BX MOV [BP-6],BX ; recvdHeader = b->pup; ; BX ← ←b MOV BX,[BP-6] MOV CX,[BX+6] ; ←recvdHeader ← CX MOV [BP-8],CX ; pktLength = (swab(recvdHeader->length)) >> 1; ; DI ← ←recvdHeader MOV DI,[BP-8] MOV BX,[DI] CALL ←swab SHR BX ; ←pktLength ← BX POP DX PUSH BX ; if (pktLength <= maxLength) MoveBlock(pkt->pup, recvdHeader, pktLength); ; BX ← ←maxLength MOV BX,[BP-4] ; CX ← ←pktLength POP CX PUSH CX CMP CX,BX JG X90 ; BX ← ←pkt MOV BX,[BP-2] MOV CX,[BX+6] PUSH CX ; BX ← ←pktLength MOV BX,[BP-10] ; CX ← ←recvdHeader MOV CX,[BP-8] CALL ←MoveBlock POP DX X90: ; if (rpct) PutChar('i'); MOV BX,←rpct OR BX,BX JZ X91 MOV BX,069X CALL ←PutChar X91: ; ReleasePBI(b); ; BX ← ←b MOV BX,[BP-6] CALL ←ReleasePBI ; if (pktLength > maxLength) SIGNAL(ReceivePktTooLong, 0); ; BX ← ←maxLength MOV BX,[BP-4] ; CX ← ←pktLength POP CX PUSH CX CMP CX,BX JLE X92 XOR BX,BX MOV CX,←ReceivePktTooLong CALL ←SIGNAL X92: ; }; MOV SP,BP POP BP RET; ; int /*BOOL*/ ; EnqueueRecvd(b) ←EnqueueRecvd: ; struct PBI *b; PUSH BP MOV BP,SP PUSH BX ; { /* the main scheduler. */ ; struct Header *header; ; int destPSB; ADD SP,0FFFCX ; header = b->pup; ; BX ← ←b MOV BX,[BP-2] MOV CX,[BX+6] ; ←header ← CX MOV [BP-4],CX ; if (header->destHost.w != myHost.w) return false; ; BX ← ←header MOV BX,[BP-4] MOV CX,[BX+8] MOV BX,WORD PTR ←myHost CMP CX,BX JZ X93 XOR BX,BX MOV SP,BP POP BP RET; X93: ; if ((header->type.fields&subtypeField) != rpc) return false; ; BX ← ←header MOV BX,[BP-4] MOV AL,[BX+3] AND AL,0E0X CMP AL,060X JZ X94 XOR BX,BX MOV SP,BP POP BP RET; X94: ; if (((header->type.fields&classField)==call) && ; ((header->type.fields&ackField)!=0)) b=b; ; BX ← ←header MOV BX,[BP-4] MOV AL,[BX+3] AND AL,7 OR AL,AL JNZ X96 ; BX ← ←header MOV BX,[BP-4] MOV AL,[BX+3] AND AL,8 OR AL,AL JZ X96 MOV AL,1 JR X97 X96: XOR AL,AL X97: OR AL,AL JZ X95 ; BX ← ←b MOV BX,[BP-2] ; ←b ← BX MOV [BP-2],BX X95: ; destPSB = header->destPSB; ; BX ← ←header MOV BX,[BP-4] MOV CX,[BX+4] ; ←destPSB ← CX POP DX PUSH CX ; recvd += 1; INC ←recvd ; if ((destPSB <= 0) || (destPSB > maxPSB) || (wanting[destPSB] == false)) { ; BX ← ←destPSB POP BX PUSH BX CMP BX,0 JLE X100 ; BX ← ←destPSB POP BX PUSH BX CMP BX,0FX JG X102 ; BX ← ←destPSB POP BX PUSH BX LEA CX,←wanting SAL BX ADD BX,CX MOV CX,[BX] OR CX,CX JNZ X101 X102: MOV AL,1 JR X103 X101: XOR AL,AL X103: OR AL,AL JZ X99 X100: MOV AL,1 JR X104 X99: XOR AL,AL X104: OR AL,AL JZ X98 ; if (idlers == 0) return false; /* server too busy, throw away */ MOV BX,←idlers OR BX,BX JNZ X105 XOR BX,BX MOV SP,BP POP BP RET; X105: ; Enqueue(&idlerQ, b); ; BX ← ←b MOV BX,[BP-2] LEA CX,←idlerQ CALL ←Enqueue ; if (rpct) PutChar('e'); MOV BX,←rpct OR BX,BX JZ X106 MOV BX,065X CALL ←PutChar X106: ; idlers -= 1; DEC ←idlers ; }; ; else { /* someone wants this packet: give them it -- */ JR X107 X98: ; if (waiterPkts[destPSB]) return false; /* two packets to same process! */ ; BX ← ←destPSB POP BX PUSH BX LEA CX,←waiterPkts SAL BX ADD BX,CX MOV CX,[BX] OR CX,CX JZ X108 XOR BX,BX MOV SP,BP POP BP RET; X108: ; waiterPkts[destPSB]=b; ; BX ← ←destPSB POP BX PUSH BX LEA CX,←waiterPkts SAL BX ADD BX,CX ; CX ← ←b MOV CX,[BP-2] MOV [BX],CX ; if (rpct) PutChar('w'); MOV BX,←rpct OR BX,BX JZ X109 MOV BX,077X CALL ←PutChar X109: ; }; X107: ; return true; MOV BX,0FFFFX MOV SP,BP POP BP RET; ; }; ; EnqueueAgain(b) ←EnqueueAgain: ; struct PBI *b; PUSH BP MOV BP,SP PUSH BX ; { ; if (EnqueueRecvd(b) == false) { ; BX ← ←b POP BX PUSH BX CALL ←EnqueueRecvd OR BX,BX JNZ X110 ; ReleasePBI(b); ; BX ← ←b POP BX PUSH BX CALL ←ReleasePBI ; if (rpct) PutChar('d'); MOV BX,←rpct OR BX,BX JZ X111 MOV BX,064X CALL ←PutChar X111: ; }; X110: ; }; MOV SP,BP POP BP RET; ; EnqueueBcst(b) ←EnqueueBcst: ; struct PBI *b; PUSH BP MOV BP,SP PUSH BX ; { /* Incoming broadcast dispatcher. */ ; struct Header *header; ; int destPSB; ADD SP,0FFFCX ; header = b->pup; ; BX ← ←b MOV BX,[BP-2] MOV CX,[BX+6] ; ←header ← CX MOV [BP-4],CX ; header->destHost.b.host = myHost.b.host; ; BX ← ←header MOV BX,[BP-4] MOV AX,WORD PTR ←myHost+1 MOV [BX+9],AL ; header->destSoc.LS = rpcSocket; ; BX ← ←header MOV BX,[BP-4] MOV BYTE PTR [BX+13],01EX ; EnqueueAgain(b); ; BX ← ←b MOV BX,[BP-2] CALL ←EnqueueAgain ; }; MOV SP,BP POP BP RET; ; static int generator; ; int NewPSB(context) ←NewPSB: ; struct RPCCtx *context; PUSH BP MOV BP,SP PUSH BX ; { /* generates non-null PSB unique to this epoch. */ ; if (++generator > maxPSB) SIGNAL(ERROR, 0); INC ←generator MOV BX,←generator CMP BX,0FX JLE X112 XOR BX,BX MOV CX,2 CALL ←SIGNAL X112: ; contexts[generator] = context; MOV BX,←generator LEA CX,←contexts SAL BX ADD BX,CX ; CX ← ←context POP CX PUSH CX MOV [BX],CX ; return generator; MOV BX,←generator MOV SP,BP POP BP RET; ; }; ; RPCInitialize(pCtxQ) ←RPCInitialize: ; struct Queue *pCtxQ PUSH BP MOV BP,SP PUSH BX ; { ; listenerRunning = (signalTimeout = true); MOV ←signalTimeout,0FFFFX MOV ←listenerRunning,0FFFFX ; minRetransmitPulses = minRetransmitMsecs; MOV ←minRetransmitPulses,0FAX ; minPingPulses = minPingMsecs; MOV ←minPingPulses,01388X ; maxPingPulses = maxPingSecs*1000; MOV ←maxPingPulses,07530X ; broadcastRetransmissions = 5; MOV ←broadcastRetransmissions,5 ; myCtxQ=pCtxQ; ; BX ← ←pCtxQ POP BX PUSH BX MOV ←myCtxQ,BX ; SignalInitialize(); CALL ←SignalInitialize ; Zero(waiterPkts, maxPSB + 1); MOV BX,010X LEA CX,←waiterPkts CALL ←Zero ; Zero(wanting, maxPSB + 1); MOV BX,010X LEA CX,←wanting CALL ←Zero ; Zero(contexts, maxPSB + 1); MOV BX,010X LEA CX,←contexts CALL ←Zero ; ReceivePktTooLong = CODE(); CALL ←CODE MOV ←ReceivePktTooLong,BX ; }; MOV SP,BP POP BP RET; ; Externals Declared Here PUBLIC ←myHost PUBLIC ←myCtxQ PUBLIC ←mySoc PUBLIC ←idlerQ PUBLIC ←broadcastRetransmissions PUBLIC ←rpct PUBLIC ←PktExchange PUBLIC ←EnqueueAgain PUBLIC ←IdleReceive PUBLIC ←EnqueueRecvd PUBLIC ←EnqueueBcst PUBLIC ←NewPSB PUBLIC ←RPCInitialize C←CODE ENDS ; Number of Bytes of Code = 08A9X, (2217)