.title idllb ;;; idllb - (priviledged) determine idle information for terminals ; ; revision history ; ; 02b 08Oct83 Rg Fix a few typos. ; 02a 08Nov82 cal .Written; this routine has been coded again from ; scratch. Revision history after this point has ; no reason for existing and can be safely ingnored. ; 01b 16jul82 vp .added .title ; 01a 12Mar82 cal .Taken from a Decus tape ; ; synopsis ; ; status = idle(buf_tim, buf_pid, buf_siz) ; ; buf_tim - buffer of longwords to receive idle times ; buf_pid - buffer of longwords to receive pids ; buf_siz - number of units to get information about ; ; Both buffers are longwords (integer*4) arrays of size buf_siz. Idle ; time and process ids are stored in the two buffers in consecutive ; elements with a zero longword in the pid buffer to mark end of the ; list. The information is ordered by terminal name. ; ; Note: Use of this routine requires the privilege CMKRNL. ; .library /SYS$LIBRARY:LIB.MLB/ $ucbdef $ddbdef $ipldef ; ; Useful constants ; off_tim = 4 ; offset to due time buffer off_pid = 8 ; offset to pid buffer off_siz = 12 ; offset to unit count num_args = 3 ; number of arguments fudge = 2 ; add this to exe$gl_abstim sizeof_long = 4 ; size of a longword max_units = 128 ; max units to report about sizeof_buf = max_units * sizeof_long ; size of return buffers .entry idle,^M cmpl #num_args,(ap) ; need this many arguments beql 10$ ; branch if correct movl #ss$_insfarg,r0 ; setup error status ret ; go give him the bad news 10$: cmpl @off_siz(ap),#max_units ; want at least this many units bgequ 20$ ; we'll allow his to be bigger movl #ss$_ivbuflen,r0 ; setup error status ret ; return to caller 20$: probew #0,#sizeof_buf,@off_tim(ap) ; see if we can write there... beql 30$ ; bail out if not probew #0,#sizeof_buf,@off_pid(ap) ; see if we can write here too bneq 40$ ; branch if we can 30$: movl #ss$_accvio,r0 ; setup error status ret ; return to caller 40$: $lkwset_s inadr=lock ; lock routine into working set cmpl #ss$_wasclr,r0 ; did we lock the pages? beql 50$ ; branch if so cmpl #ss$_wasset,r0 ; were they already locked? bneq err ; if not, then error 50$: $cmkrnl_s routin=idlekrn ; do the privileged stuff movl r0,r6 ; save status for later $ulwset_s inadr=lock ; unlock kernel routine cmpl #ss$_wasclr,r0 ; did we unlock the pages? beql 60$ ; branch if so cmpl #ss$_wasset,r0 ; were they already unlocked? bneq err ; if not, then error 60$: movc3 al_cnt,bl_tim,@off_tim(ap) ; store idle time info movc3 al_cnt,bl_pid,@off_pid(ap) ; store pid info movl r6,r0 ; restore status err: ret ; that's all folks! ; ; Descriptor used to lock kernel routine into our working set ; lock: .address idlekrn .address idlekrnend ; ; Entry point for the privileged search and slurp. The following ; registers are used: ; ; r0 - return status ; r1 thru r5 - scratch ; r6 - system absolute time ; r9 - address of due time storage area ; r8 - address of pid storage area ; r10 - address of current unit control block ; r11 - address of current device data block ; .entry idlekrn,^M movl #bl_tim,r9 ; address of due time buffer movl #bl_pid,r8 ; address of pid buffer jsb sch$iolockr ; lock io data base for read dsbint #ipl$_synch ; raise ipl while mucking... addl3 #fudge,exe$gl_abstim,r6 ;; add fudge to abstim movl ioc$gl_devlist,r11 ;; ddb list in r11 brb jump1 ;; jump into middle loop loop1: movl ddb$l_link(r11),r11 ;; look at next ddb jump1: beql finish ;; already did last controller movl ddb$l_ucb(r11),r10 ;; fetch first ucb of this ddb brb jump2 ;; jump into innermost loop loop2: movl ucb$l_link(r10),r10 ;; look at next ucb jump2: beql loop1 ;; no more units left cmpb #dc$_term,ucb$b_devclass(r10) ;; is this unit a terminal? bneq loop1 ;; next ddb if not tstl ucb$l_pid(r10) ;; check for a process beql loop2 ;; skip if no process subl3 ucb$l_duetim(r10),r6,r2 ;; idle time in r2 bbc #ucb$v_tim,ucb$w_sts(r10),10$ ;; see if unit is timed out brb 20$ ;; timed out so go zero time 10$: bbs #ucb$v_bsy,ucb$w_sts(r10),30$ ;; see if unit is busy 20$: clrl r2 ;; if true, zero idle time 30$: movl r2,(r9)+ ;; stow idle time movl ucb$l_pid(r10),(r8)+ ;; stow owner pid cmpl #bl_pid+sizeof_buf,r8 ;; have we run out of buffer? bgequ loop2 ;; if not negative we're ok subl #sizeof_long,r8 ;; backup just a tad movl #ss$_bufferovf,r0 ;; setup return status brb krnerr ;; and exit finish: movl #ss$_normal,r0 ;; setup return status krnerr: movl r0,r6 ;; store status jsb sch$iounlock ;; unlock io data base enbint ;; restore ipl clrl (r8)+ ; flag end of list subl3 #bl_pid,r8,al_cnt ; calculate size of transfer movl r6,r0 ; restore status ret ; back to user mode bl_tim: .blkl sizeof_buf ; storage for due time bl_pid: .blkl sizeof_buf ; storage for pid al_cnt: .long 0 ; size of transfer idlekrnend: ; end of locked memory .end