;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Program: load_block_counter.mar ; Author: Billy Bitsenbites (Bruce Ellis) ; Date written: Sometime in January 1986 ; ; Synopsis: This guy prompts for a disk device name ; and looks up its UCB address. He ; then allocates a chunk of nonpaged pool ; and copies the monitoring code into the ; allocated pool. To get the code activated ; he saves the start i/o address from the ; DDT and moves the address of the code ; in pool to the start i/o address in the ; DDT. When the start i/o entry point ; is entered, the code has the address of the ; IRP passed to it in R3. He checks for ; paging, swapping, and split i/os. He also ; counts the number of read, writes and the ; size of each. ; ; Modifications: ; BAE 9/24/87: Add code to count the split i/os. ; BAE 5/90: Update synchronization for V5. ; ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .library /sys$library:lib.mlb/ .link /sys$system:sys.stb/ $ddtdef $ucbdef $irpdef $ipldef header=12 ;12 byte header for the pool devnam: .long 15 ;storage for the disk device name .address 10$ 10$: .blkb 15 dev_prompt: ;Prompt for device name .ascid /enter disk to be monitored:/ l_adr: .address l_s .address l_e .entry load_block_ctr,^m<> ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Get device name to monitor ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pushal devnam ;pass the length address pushal dev_prompt ;pass the prompt pushal devnam ;address of desc. to store device name calls #3,g^lib$get_input ;Get the device name blbs r0,lab1 $exit_s r0 lab1: $lkwset_s inadr=l_adr ;lock code running at high ipl blbs r0,lab2 $exit_s r0 ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Load the code to monitor disk activity ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lab2: $cmkrnl_s routin=kernel_setup ret ;*********************************************************************** ; Kernel mode setup code ;*********************************************************************** .entry kernel_setup,^m ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Grab a write mutex on the i/o database ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ moval g^ioc$gl_mutex,r0 ;Grab a write mutex on the jsb g^sch$lockw ; i/o database (Note this code ; assumes that the change mode ; dispatcher has set up R44 to point ; to the PCB) ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Search for ucb address of this device ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ moval devnam,r1 ;Pass the address of the device name ; descriptor. jsb g^ioc$searchdev ;Search the i/o database for the UCB blbs r0,no_dev_error ;If error scram ; of the device (r1<-UCB address) pushl r0 ;save status brw dev_error no_dev_error: pushl r1 ;Save the ucb address movl #code_len+header,r1 ;else grab a chunk of pool to jsb g^exe$alononpaged ; load the code into blbs r0,no_pool_error ;on error scram pushl r0 ;save error status brb pool_error no_pool_error: movzwl r1,8(r2) ;init the size field for deallocation movl r2,g^exe$gl_sitespec ;save the pointer to pool ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Copy the code into pool ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pushr #^m movc3 #code_len,pool_code_start,12(r2) popr #^m popl r1 ;restore the ucb address l_s: forklock ucb$b_flck(r1) ;Synch with driver at Fork ipl movl ucb$l_ddt(r1),r5 ;get the driver dispatch table address movl ddt$l_start(r5),header(r2) ;save actual start i/o ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; reset the start i/o to point to our code ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ moval get_block_info-pool_code_start+header(r2),ddt$l_start(r5) ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Save the unit number of the disk ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ movzwl ucb$w_unit(r1),unit-pool_code_start+header(r2) forkunlock lock=ucb$b_flck(r1),newipl=#ipl$_astdel l_e: pushl #ss$_normal ;set success status dev_error: pool_error: moval g^ioc$gl_mutex,r0 ;Free up the mutex on the io database movl g^ctl$gl_pcb,r4 ; jsb g^sch$unlock ;get status popl r0 ret ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Pool code to check each i/o request processed by ; the start i/o routine ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pool_code_start: saved_start: .blkl 1 read_count: .long 0 read_lengths: .long 0[129] write_count: .long 0 write_lengths: .long 0[129] paging_ios: .long 0 swap_ios: .long 0 unit: .long 0 splits: .long 0 get_block_info: pushr #^m cmpw unit,ucb$w_unit(r5) ;this the unit to be monitored? beql ours ; brw exit ;if not scram ours: bbc #irp$v_pagio,irp$w_sts(r3),no_page ;Paging i/o? incl paging_ios ;if so increment count no_page: bbc #irp$v_swapio,irp$w_sts(r3),no_swap ;Swapping i/o? incl swap_ios ;if so increment count no_swap: extzv #io$v_fcode,#io$s_fcode,irp$w_func(r3),r2 ;get function ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Check for reads ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cmpb #io$_readvblk,r2 ;Read virtual? beql handle_reads cmpb #io$_readlblk,r2 ;Read logical? beql handle_reads cmpb #io$_readpblk,r2 ;Read physical? beql handle_reads ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Check for writes ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cmpb #io$_writevblk,r2 ;Write virtual? beql handle_writes cmpb #io$_writelblk,r2 ;Write logical? beql handle_writes cmpb #io$_writepblk,r2 ;Write physical? beql handle_writes brw exit handle_reads: incl read_count ;increment read count movl irp$l_bcnt(r3),r2 ;determine the size divl2 #512,r2 ;Compute the size in blocks cmpl r2,#127 ;if > 127 blocks note in 127 blequ ok1 movl #128,r2 ok1: incl read_lengths[r2] ;increment size counter brw check_splits handle_writes: incl write_count ;increment write count movl irp$l_bcnt(r3),r2 ;determine the size divl2 #512,r2 ;Compute size in blocks cmpl r2,#127 ;if > 127 then set to 127 blequ ok2 movl #128,r2 ok2: incl write_lengths[r2] ;increment write size counter check_splits: ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; If not a virtual i/o then it cannot be a split i/o. ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bbc #irp$v_virtual,irp$w_sts(r3),exit tstl irp$l_abcnt(r3) ;If accumulated byte count ; is 0 this is either not a split ; i/o or it is the first pass ; prior to the split so skip it. beql exit incl splits ; else increment split count exit: popr #^m jmp @saved_start ;Goto driver start i/o routine pool_code_end: code_len = pool_code_end-pool_code_start ;amount of pool to allocate .end load_block_ctr == [figure 21] ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Program: dump_block_counts ; Author: Billy Bitsenbites (Bruce Ellis) ; Date written: Sometime in January ; ; Synopsis: This guy dumps the block counts ; monitored by the load_block_counter ; program. ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .macro check ?l blbs r0,l $exit_s r0 l: .endm check .library /sys$library:lib.mlb/ .link /sys$system:sys.stb/ long=4 base=12 c_off=base saved_start=c_off c_off=c_off+long read_count=c_off c_off=c_off+long read_lengths=c_off c_off=c_off+ write_count=c_off c_off=c_off+long write_lengths=c_off c_off=c_off+ paging_ios=c_off c_off=c_off+long swap_ios=c_off c_off=c_off+long splits=c_off+ c_off=c_off+<2*long> data: .blkb c_off ;Data returned from block counter general_fmt: .ascid - /Read:!10UL Writes:!10UL Paging ios:!10UL Swapping ios:!5UL/ split_fmt: .ascid /Split ios on this disk: !10UL/ line_fmt: .ascid /!AD:!10UL!10UL!10UL!10UL!10UL/ pre_list: .ascii / 0 - 4/ pre_len=.-pre_list .ascii / 5 - 9/ .ascii / 10 - 14/ .ascii / 15 - 19/ .ascii / 20 - 24/ .ascii / 25 - 29/ .ascii / 30 - 34/ .ascii / 35 - 39/ .ascii / 40 - 44/ .ascii / 45 - 49/ .ascii / 50 - 54/ .ascii / 55 - 59/ .ascii / 60 - 64/ .ascii / 65 - 69/ .ascii / 70 - 75/ .ascii / 75 - 79/ .ascii / 80 - 85/ .ascii / 85 - 89/ .ascii / 90 - 94/ .ascii / 95 - 99/ .ascii / 100 - 104/ .ascii / 105 - 109/ .ascii / 110 - 114/ .ascii / 115 - 119/ .ascii / 120 - 124/ .ascii / 125 - 128+/ buffer: .long 80 .address 10$ 10$: .blkb 80 nlines=25 read_header: .ascid /Breakdown of Reads by block size:/ write_header: .ascid /Breakdown of writes by block size:/ ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Program to format and dump block counts ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .entry dump_block_counts,^m<> $cmkrnl_s routin=return_counts check ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Format and spill general information ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ $fao_s ctrstr=general_fmt,outbuf=buffer,outlen=buffer,- p1=data+read_count- p2=data+write_count,p3=data+paging_ios,p4=swap_ios check pushal buffer calls #1,g^lib$put_output check movl #80,buffer ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Format and spill split io information ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ $fao_s ctrstr=split_fmt,outbuf=buffer,outlen=buffer,- p1=data+splits check pushal buffer calls #1,g^lib$put_output check ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Format and spill read header ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ movl #80,buffer pushal read_header calls #1,g^lib$put_output check ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Format and spill each line of read information ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ movl #nlines,r5 moval pre_list,r3 moval data+read_lengths,r2 dump_read: $fao_s ctrstr=line_fmt,outbuf=buffer,outlen=buffer,p1=#10- p2=r3,p3=(r2),p4=4(r2),p5=8(r2),p6=12(r2),p7=16(r2) check pushal buffer calls #1,g^lib$put_output check addl #pre_len,r3 addl #4*5,r2 movl #80,buffer sobgtr r5,dump_read ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Format and spill last line of read information ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ $fao_s ctrstr=line_fmt,outbuf=buffer,outlen=buffer,p1=#10- p2=r3,p3=(r2),p4=4(r2),p5=8(r2),p6=#0,p7=#0 check pushal buffer calls #1,g^lib$put_output check ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Format and spill write header ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pushal write_header calls #1,g^lib$put_output check movl #nlines,r5 moval pre_list,r3 moval data+write_lengths,r2 ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Format and spill each line of write information ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dump_write: $fao_s ctrstr=line_fmt,outbuf=buffer,outlen=buffer,p1=#10- p2=r3,p3=(r2),p4=4(r2),p5=8(r2),p6=12(r2),p7=16(r2) check pushal buffer calls #1,g^lib$put_output check addl #pre_len,r3 addl #4*5,r2 movl #80,buffer sobgtr r5,dump_write ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Format and spill last line of write information ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ $fao_s ctrstr=line_fmt,outbuf=buffer,outlen=buffer,p1=#10- p2=r3,p3=(r2),p4=4(r2),p5=8(r2),p6=#0,p7=#0 check pushal buffer calls #1,g^lib$put_output check ret ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Return block counter information ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .entry return_counts,^m movl g^exe$gl_sitespec,r2 ;Check to see if block counter beql accvio ; is loaded. movc3 #c_off,(r2),data ;copy the data up from pool movl #ss$_normal,r0 exit: ret ;fini accvio: movl #ss$_accvio,r0 brb exit .end dump_block_counts == [figure 22] ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Program: Unload_block_counter ; Author: Billy Bitsenbites (Bruce Ellis) ; Synopsis: Cleans up after disk monitor. ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .library /sys$library:lib.mlb/ .link /sys$system:sys.stb/ $ddtdef $ucbdef $irpdef header=12 devnam: .long 15 .address 10$ 10$: .blkb 15 dev_prompt: .ascid /enter disk to be unmonitored:/ .entry unload_block_ctr,^m<> ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Get device name to unload monitor for ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pushal devnam pushal dev_prompt pushal devnam calls #3,g^lib$get_input blbs r0,lab $exit_s r0 ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; UNLoad the code to monitor disk activity ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lab: $cmkrnl_s routin=kernel_setup ret ;*********************************************************************** ; Kernel mode setup code ;*********************************************************************** .entry kernel_setup,^m tstl g^exe$gl_sitespec ;if not loaded scram bneq cont movl #ss$_accvio,r0 ret cont: ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Grab a write mutex on the i/o database ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ moval g^ioc$gl_mutex,r0 jsb g^sch$lockw ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Search for ucb address of this device ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ moval devnam,r1 jsb g^ioc$searchdev blbs r0,no_dev_error ;If error scram pushl r0 brb dev_error no_dev_error: movl g^exe$gl_sitespec,r0 ;save the pointer to pool ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; reset the start i/o to point to original and deallocate code ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ movl ucb$l_ddt(r1),r5 ;get the driver dispatch table address movl header(r0),ddt$l_start(r5) ;save actual start i/o jsb g^exe$deanonpaged ;give up the pool clrl g^exe$gl_sitespec ;mark the sitespec as unused pushl #ss$_normal dev_error: moval g^ioc$gl_mutex,r0 ;Free up the mutex on the io database movl g^ctl$gl_pcb,r4 jsb g^sch$unlock popl r0 ret .end unload_block_ctr