.Title THRASH - for trying out the queuing DU handler .Nlist bex .Enabl gbl .if eq 1 ****************************************************************************** * Requires linking with CVLLIB.OBJ * ****************************************************************************** .endc .psect mesage con vermes: .ascii /Thrash V3a/<0> .psect .if eq 1 THRASH is designed for thrashing disc devices, especially using handlers capable of internal queueing. It was written to thrash the DU handler written for Webster Computer Corporation, Melbourne, Australia. It performs reads only, reading but one word per request, in any of the patterns RANDOM, BUTTERFLY, SEQUENTIAL, and DECREASING SEQUENTIAL. V1 25-Nov-84 Chester Wilson, Charleville, Australia 4470. V2 15-Aug-85 Add file lookup. V3 27-Sep-85 Search for unused completion routine rather than using next blindly. Add START & END. V3a 14-Jun-86 bug fix .endc .mcall .qset,.readc,.gtim,.lookup,.gtlin,.ttinr,.spfun,.writw,.enter,.wait .mcall .spnd,.rsum,.cstat,.print,.csigen,.ttyin,.sreset,.exit jsw=44 gtlin$=10 tcbit$=100 ttspc$=10000 ttlc$=40000 userrb=53 error$=4 cr=15 lf=12 .Sbttl Macros .macro type arg .save .psect mesage con $$$=. .ascii arg .restore mov r0,-(sp) mov #$$$,r0 emt ^o351 mov (sp)+,r0 .endm type .macro tx arg .save .psect mesage con $$$=. .ascii arg .restore .endm tx .macro movs string,loc .save .psect mesage con $$$=. .ascii string .restore mov #$$$,loc .endm movs .macro ref string .save .psect mesage con $$$=. .ascii string .restore .word $$$ .endm ref .macro gtlin prompt,buffer .save .psect mesage con $$$=. .ascii prompt .restore .gtlin buffer,#$$$ .endm gtlin .Sbttl Data Locations lo: 0 ;Locations used in the routines for getting the hi: 0 ; next block. blkflg: 0 size: 0 ;For the device size in blocks. blksub: 0 ;Gets address of routine for getting next block passes: 0 ;Current pass count pasmax: 0 ;Number of passes requested by the user tecnic: 0 ;Stores type of technique used for thrashing offset: 0 ;Starting block if offsets used. .iif ndf maxq$, maxq$=20. ;Number of queued requests allowed for. .iif gt maxq$ - <32.>, .error ;32 is the number of requests which can be handled ;at any one time by the DU handler. qarea: .blkw 10.*34. ;Queue area required by RT but not by TSX ; (TSX uses MAXQ to limit number of requests) area: .blkw 7 ;General EMT area queued: 0 ;Number of requests currently queued. crtab: ;Table of completion routine addresses. .word cr1,cr2,cr3,cr4,cr5 .word cr6,cr7,cr8,cr9,cr10 .word cr11,cr12,cr13,cr14,cr15 .word cr16,cr17,cr18,cr19,cr20 .word cr21,cr22,cr23,cr24,cr25 .word cr26,cr27,cr28,cr29,cr30 .word cr31,cr32,cr33,cr34,cr35 blktab: .blkw 35. ;Table of block numbers of current requests buffer: .blkw 35. ;Area for reading information into. used: .blkw 35. ;Zero if this completion routine/block no unused. listit:0 tty: .rad50 /tt / defext: .rad50 /dsk / maxq: 0 ;Number of queue elements in use. outcnt: 0 ;For line formatting tblk: 0 ;TT output block number tbuff: .blkw 100. ;For terminal output logtab: .blkw 200. ;To record blocks read. logend: ;End of buffer logrep: 0 ;Pointer for blocks queued logred: 0 ;Pointer for blocks actually read limit: .limit himem: 0 .Sbttl Initialization & Setting up User Requirements .Enabl lsb Badrun:: bisb #error$,@#userrb Start:: .sreset bisb #ttlc$,@#jsw bicb #gtlin$,@#jsw .csigen limit+2,#defext mov r0,himem bisb #gtlin$,@#jsw .wait #3 bcc 10$ .print #vermes br start 10$: .cstat #area,#3,#tbuff ;Try for size from CSTAT in case file. mov tbuff+4,size bne 20$ .spfun #area,#3,#373,#size,#0,#0 ;Get its size with SPFUN if device. bcc 20$ type <#?Thrash-E-Cannot obtain device size#<0>> br badrun 20$: .enter #area,#1,#tty ;Open a terminal channel bcc 30$ type <#?Thrash-E-Cannot open device TT:#<0>> bisb #error$,@#userrb .exit 30$: ;*************************************************************************** ; Number of active queue elements allowed [32]: ;*************************************************************************** clr queued gtlin >,#tbuff mov #tbuff,r1 call rd tst r0 beq 40$ cmp r0,#32. blos 50$ type > bisb #error$,@#userrb br 30$ 40$: mov #32.,r0 ;Default is 32. 50$: add #2,r0 ;Add 2 for terminal & spare mov r0,maxq .qset #qarea,maxq sub #2,maxq ;*************************************************************************** ; Do you want a list of the blocks [N]? ;*************************************************************************** clr listit gtlin >,#tbuff movb tbuff,r0 bic #40,r0 cmp r0,#'Y beq 60$ dec listit 60$: ;*************************************************************************** ; Number of passes (0 for continuous) [0]: ;*************************************************************************** mov #tbuff,r1 gtlin >,r1 call rd mov r0,pasmax clr passes 70$: ;*************************************************************************** ; nnnnn blocks available. ; Start [0]: ; End [nnn]: ;*************************************************************************** call tcrlf mov size,r3 clr r2 call wd2t type > mov #tbuff,r1 gtlin >,r1 call rd cmp r0,size blo 80$ type > bisb #error$,@#userrb br 70$ 80$: mov r0,offset mov #tloub,r1 ;Set up buffer with END message movs >,r2 ; containing actual size. 90$: movb (r2)+,(r1)+ bne 90$ dec r1 mov size,r3 dec r3 clr r2 call wd2 movs >,r2 100$: movb (r2)+,(r1)+ bpl 100$ mov #tbuff,r1 .gtlin r1,#tloub call rd tst r0 beq 120$ cmp r0,offset bhis 110$ type > bisb #error$,@#userrb br 70$ 110$: cmp r0,size blos 130$ type > bisb #error$,@#userrb br 70$ 120$: mov size,r0 dec r0 130$: mov r0,size sub offset,size inc size ;One past last block number. ;*************************************************************************** ; Random, Butterfly, Sequential, or Decreasing Sequential [B]? ;*************************************************************************** 140$: gtlin >,#tbuff movb tbuff,r1 bne 150$ movb #'B,r1 150$: bic #40,r1 ;(upper case) movb r1,tecnic ;Remember technique required xxrun: cmp r1,#'R beq xxran cmp r1,#'B beq xxbut cmp r1,#'S beq xxseq cmp r1,#'D beq xxdsq type > bisb #error$,@#userrb br 140$ xxran: ;Wants RANDOM blocks read mov #blkran,blksub mov size,blkflg inc blkflg .gtim #area,#tbuff mov tbuff,ran$nm ;Prime the random number generator br 160$ xxbut: ;Wants BUTTERFLY sequence mov #blkbut,blksub clr blkflg clr lo mov size,hi dec hi br 160$ xxseq: ;Wants SEQUENTIAL reading mov #blkseq,blksub clr lo br 160$ xxdsq: ;Wants DECREASING SEQUENTIAL mov #blkdsq,blksub mov size,hi dec hi 160$: clr tblk ;TT output block count clr outcnt ;Counter of items on line mov #logtab,logrep ;Pointer to next block to report mov #logtab,logred ;Pointer to next slot for read block mov #used,r0 mov #35.,r1 170$: clr (r0)+ ;Clear USED words dec r1 bne 170$ .Dsabl lsb .Sbttl Block Reading & Reporting Loop ;You may well wonder why the block reporting was done using a table of ; returned values rather than output from the completion routines. ; This was most interesting: ; If output was done from the completion routines using .PRINT ; the output from one completion routine could be mixed ; within the output from the main routine ; If output was done from the completion routines using .WRITW ; the monitor screwed up its list of queue elements ; (see THRASH.QRY) and hung. This was not tested under ; TSX. The list of queues was actually fragmented into ; three queues, with only one active for some time ; thereby ruining the idea of internal queuing in the DU ; handler! .Enabl lsb Bloop: clr r5 ;Pointer within completion/block/used 10$: ; tables. call report ;Report any processed since last time. ; **** Get next block and check for end of pass **** 20$: call @blksub ;Get next block bcc 50$ ;Not end of pass .wait #3 .wait #1 call report ;Report any we may have missed. type </End of Pass /<200>> inc passes mov passes,r0 call wdt call tcrlf mov tecnic,r1 tst pasmax beq 30$ ;If no limit, continue cmp passes,pasmax bhis 40$ 30$: jmp xxrun 40$: type </End of Run/<0>> jmp start ; **** Queue this block for reading **** 50$: cmp queued,maxq ;See if room for more blo 60$ mov r0,-(sp) .spnd ;Have a blow. mov (sp)+,r0 br 50$ 60$: tst used(r5) beq 70$ add #2,r5 cmp r5,#35.*2 blo 60$ clr r5 br 60$ 70$: inc used(r5) mov r0,blktab(r5) cmpb tecnic,#'R ;If random, need to report blocks bne 80$ ; as they are queued as well as on mov #'Q,r3 ; return. call tell 80$: mov #2,r3 ;Allow 2 tries if error, as channel mov #buffer,r4 ; gets fouled up if get one. add r5,r4 90$: .readc #area,#3,r4,#1,crtab(r5),blktab(r5) bcc 100$ dec r3 bne 90$ type <#?Thrash-E-Input Error on .READC - block #<200>> bisb #error$,@#userrb mov blktab(r5),r3 clr r2 call wd2t call tcrlf 100$: inc queued ;Increment count of queued requests jmp 10$ .Dsabl lsb .Sbttl Report - Report any blocks read since last queuing request .Enabl lsb Report: cmp logrep,logred bne 5$ ;No more blocks to report return 5$: clr r3 cmp tecnic,#'R ;If RANDOM, reporting queued as well. bne 10$ mov #'R,r3 10$: mov @logrep,r0 ;Block number add #2,logrep mov @logrep,r1 ;Status word add #2,logrep call tell bic #^c1,r1 ;Check error bit beq 30$ ;OK mov r0,r3 ;Error - tell him block number. .wait #3 .wait #1 bisb #error$,@#userrb type </Error Reading Block: /<200>> clr r2 call wd2pt type </Type to continue /<200>> 20$: .ttyin cmpb r0,#lf bne 20$ 30$: cmp logrep,#logend blo report mov #logtab,logrep br report .Dsabl lsb .Sbttl Block Getting Routines blkran: ;RANDOM blocks dec blkflg beq endpass ;(blkflg used as a counter) mov size,r0 call iran ;Random number routine from CVLLIB br notend blkbut: ;BUTTERFLY pattern inc blkflg bit #1,blkflg beq 10$ mov lo,r0 cmp r0,size bhis endpass inc lo br notend 10$: mov hi,r0 cmp r0,#-1 beq endpass dec hi br notend blkseq: ;SEQUENTIAL pattern mov lo,r0 inc lo cmp r0,size bhis endpass br notend blkdsq: ;DECREASING SEQUENTIAL pattern mov hi,r0 dec hi cmp r0,#-1 bne notend endpass: sec return notend: add offset,r0 clc return .Sbttl Writing to the Terminal .Enabl lsb ;Expects: number in R0 ; R3 / 0 if no letter to be appended, or ASCII letter if required ; (used with RANDOM to differentiate between blocks ; queued and blocks returned). Tell: tst listit bne notell mov r0,-(sp) mov r1,-(sp) mov r2,-(sp) mov r3,-(sp) bne 10$ mov #40,r3 ;Space in R3 if zero given. 10$: mov #tbuff,r1 mov #7.,r2 ;7 positions + 1 for letter call wdpx ;Write decimal + positions movb r3,(r1)+ ;Insert letter (or space) inc outcnt cmp outcnt,#8. ;8 per line blt 20$ movb #cr,(r1)+ movb #lf,(r1)+ clr outcnt 20$: clrb (r1)+ ;Clear out succeeding bytes clrb (r1)+ 30$: tstb -(r1) ;Now go back to last non-zero byte beq 30$ sub #tbuff-2,r1 asr r1 ;Number of words .writw #area,#1,#tbuff,r1,tblk bcc 40$ type > mov tblk,r0 call wdt type > bisb #error$,@#userrb .exit 40$: inc tblk mov (sp)+,r3 mov (sp)+,r2 mov (sp)+,r1 mov (sp)+,r0 notell: return .Dsabl lsb wdpx: ;Use double word output as otherwise mov r0,-(sp) ; get signed block numbers. mov r2,-(sp) mov r3,-(sp) ;(This is the hasty lazy way to do it) mov r2,r0 mov 4(sp),r3 clr r2 call wd2p mov (sp)+,r3 mov (sp)+,r2 mov (sp)+,r0 return .Sbttl Completion Routines ;There have to be at least as many completion routines as there ; are + ; or you can get lost data by its being overwritten in the tables. cr1: mov #<2*0.>,-(sp) br crtell cr2: mov #<2*1.>,-(sp) br crtell cr3: mov #<2*2.>,-(sp) br crtell cr4: mov #<2*3.>,-(sp) br crtell cr5: mov #<2*4.>,-(sp) br crtell cr6: mov #<2*5.>,-(sp) br crtell cr7: mov #<2*6.>,-(sp) br crtell cr8: mov #<2*7.>,-(sp) br crtell cr9: mov #<2*8.>,-(sp) br crtell cr10: mov #<2*9.>,-(sp) br crtell cr11: mov #<2*10.>,-(sp) br crtell cr12: mov #<2*11.>,-(sp) br crtell cr13: mov #<2*12.>,-(sp) br crtell cr14: mov #<2*13.>,-(sp) br crtell cr15: mov #<2*14.>,-(sp) br crtell cr16: mov #<2*15.>,-(sp) br crtell cr17: mov #<2*16.>,-(sp) br crtell cr18: mov #<2*17.>,-(sp) br crtell cr19: mov #<2*18.>,-(sp) br crtell cr20: mov #<2*19.>,-(sp) br crtell cr21: mov #<2*20.>,-(sp) br crtell cr22: mov #<2*21.>,-(sp) br crtell cr23: mov #<2*22.>,-(sp) br crtell cr24: mov #<2*23.>,-(sp) br crtell cr25: mov #<2*24.>,-(sp) br crtell cr26: mov #<2*25.>,-(sp) br crtell cr27: mov #<2*26.>,-(sp) br crtell cr28: mov #<2*27.>,-(sp) br crtell cr29: mov #<2*28.>,-(sp) br crtell cr30: mov #<2*29.>,-(sp) br crtell cr31: mov #<2*30.>,-(sp) br crtell cr32: mov #<2*31.>,-(sp) br crtell cr33: mov #<2*32.>,-(sp) br crtell cr34: mov #<2*33.>,-(sp) br crtell cr35: mov #<2*34.>,-(sp) crtell: add #used,(sp) clr @(sp) add #blktab-used,(sp) mov @(sp)+,@logred add #2,logred mov r0,@logred add #2,logred cmp logred,#logend blo 10$ mov #logtab,logred 10$: dec queued .rsum return .end start