.TITLE PREMPT Buffer preemption policy .NLIST BEX .ENABL LC ; ; Pdp11/dcn buffer preemption policy ; ; This policy finds the maximum-size subsequence over all subsequences ; containing packets from the same device. ; ; External symbols ; ; Entry symbols ; .GLOBL PREMPT ;buffer preemption policy .GLOBL QUENCH ;buffer quench policy .GLOBL PRECED ;buffer precedence queueing policy .GLOBL WOLFF ;precedence assignment policy ; ; System definitions ; .ASECT .MCALL .COM ;dcnlib definitions .MCALL $DFIH,$DFSIG ;moslib definitions .COM ;define common data $DFIH ;define internet header $DFSIG ;define interprocess signals ; ; Module definitions ; S.TEL = 23.*400 ;telnet port (byte-swapped) ; ; Procedure segments ; ; Supervisor-state procedure ; .PSECT $KERI,RO,I ; ; Preemption policy ; r0 = preemptable thread head, returns r0 = buffer pointer, cc(z) = 1 if none ; PREMPT: MOV R2,-(SP) ;save CLR WEIGHT ;initialize to scan preemptable buffer thread CLR PMPCNT CLR MSGPTR MOV R0,R2 1$: MOV @R2,R2 ;get next message queue pointer BEQ 2$ ;branch if none MOV R2,R0 ;scan message queue JSR PC,QUEUE CMP R0,WEIGHT ;is this max weight BLO 1$ ;branch if no CMP 4(R2),PMPCNT BLO 1$ ;branch if no MOV R0,WEIGHT ;yes. save info MOV 4(R2),PMPCNT MOV R1,MSGPTR BR 1$ ; 2$: CLR R0 ;is there a loser buffer MOV MSGPTR,R1 BEQ 3$ ;branch if no MOV 2+SD.ADR(R1),R0 ;yes. steal user buffer CLR 2+SD.ADR(R1) 3$: MOV (SP)+,R2 ;evas TST R0 ;set cc RTS PC ; ; Quench policy ; r0 = preemptable buffer link pointer ; returns r0 = total weight, r1 = pointer to preemptable ipc message ; (zero if none) ; QUENCH: JSR PC,QUEUE ;scan message queue TST R1 BEQ 1$ ;branch if no preemptable ipc message MOV 2+SD.ADR(R1),R1 ;get user buffer pointer 1$: RTS PC ; ; Queue scan ; r0 = preemptable buffer link pointer ; returns r0 = total weight, r1 = pointer to preemptable ipc message ; (zero if none) ; QUEUE: MOV R2,-(SP) ;save MOV R3,-(SP) MOV R4,-(SP) MOV R5,-(SP) MOV 2(R0),R2 ;get queue pointer CLR R0 ;initialize CLR R1 1$: MOV @R2,R2 ;get next queue element BEQ 4$ ;branch if none CMPB #PKTCTL,2+SD.CTL(R2) BNE 1$ ;branch if not packet buffer CMPB #SG.INP,2+SD.CHN(R2) BNE 1$ ;branch if not preemptable MOV 2+SD.ADR(R2),R4 BEQ 1$ ;branch if no buffer attached CLR -(SP) ;scan for dupes MOV R2,R3 2$: CMPB #PKTCTL,2+SD.CTL(R3) BNE 3$ ;branch if not packet buffer CMPB #SG.INP,2+SD.CHN(R3) BNE 3$ ;branch if not preemptable MOV 2+SD.ADR(R3),R5 BEQ 3$ ;branch if no buffer attached CMP IH.SRC(R4),IH.SRC(R5) BNE 3$ ;branch if different source CMP IH.SRC+2(R4),IH.SRC+2(R5) BNE 3$ ;branch if different source ADD PH.WGT(R5),@SP ;same source. accumulate weight 3$: MOV @R3,R3 ;get next queue element BNE 2$ ;branch if got MOV (SP)+,R3 ;is new weight largest BEQ 1$ ;branch if none CMP R3,R0 BLO 1$ ;branch if no MOV R3,R0 ;yes. remember it MOV R2,R1 BR 1$ ; 4$: MOV (SP)+,R5 ;evas MOV (SP)+,R4 MOV (SP)+,R3 MOV (SP)+,R2 RTS PC ; ; Buffer precedence policy ; r0 = message pointer, r1 = message queue pointer ; PRECED: MOV R2,-(SP) ;save MOV R3,-(SP) MOV R1,R3 MOV R0,-(SP) CMPB #PKTCTL,2+SD.CTL(R0) ;no. is this preemptable buffer BNE 3$ ;branch if no CMPB #SG.INP,2+SD.CHN(R0) BNE 3$ ;branch if no MOV 2+SD.ADR(R0),R0 BEQ 3$ ;branch if no (user signal) MOV PH.PRC(R0),WEIGHT ;save precedence 1$: MOV @R3,R2 ;scan queue for other packet buffers BEQ 4$ ;branch if end CMPB #PKTCTL,2+SD.CTL(R2) ;is this preemptable buffer BNE 2$ ;branch if no CMPB #SG.INP,2+SD.CHN(R2) BNE 2$ ;branch if no MOV 2+SD.ADR(R2),R0 BEQ 2$ ;branch if no CMP PH.PRC(R0),WEIGHT ;yes. is it lower precedence BLO 4$ ;branch if yes 2$: MOV R2,R3 ;no. advance to next entry BR 1$ ; 3$: TST @R1 ;is queue empty BEQ 4$ ;branch if yes MOV 2(R1),R3 ;no. use last pointer 4$: MOV (SP)+,R0 ;link new entry on queue MOV @R3,@R0 BNE 5$ MOV R0,2(R1) 5$: MOV R0,@R3 MOV (SP)+,R3 ;evas MOV (SP)+,R2 RTS PC ; .PSECT $SUPI,RO,I ; ; Precedence and weight assignment policies ; r1 = buffer pointer (preserve r0) ; ; Note: Precedence is established by a sixteen-bit field. The high-order eight ; bits are copied from the TOS field in the IP datagram. The low-order eight ; bits are set at one for tcp/telnet and zero otherwise. Weight is established ; by a sixteen-bit field, which is set at the number of octets in the datagram ; rounded up to the next 64-octet boundary. ; WOLFF: MOV R0,-(SP) ;save MOV PH.OFS(R1),R0 ;compute total length ADD PH.LNG(R1),R0 ADD #77,R0 ;round up to 64-octet boundary BIC #77,R0 MOV R0,PH.WGT(R1) CLRB PH.PRC(R1) ;set precedence field MOVB IH.TOS(R1),PH.PRC+1(R1) CMPB IH.PRO(R1),#P.TCP ;is this tcp-telnet BNE 2$ ;branch if no MOV R1,R0 ADD PH.OFS(R1),R0 CMP (R0)+,#S.TEL BEQ 1$ ;branch if yes CMP (R0)+,#S.TEL BNE 2$ ;branch if no 1$: INC PH.PRC(R1) ;yes. bump precedence 2$: MOV (SP)+,R0 ;evas RTS PC ; ; Supervisor data ; (initialized at restart) ; .PSECT $ERAS,RW,I ; WEIGHT: .BLKW 1 ;queue weight PMPCNT: .BLKW 1 ;packets since last preemption MSGPTR: .BLKW 1 ;message pointer ; .END