[comp.os.vms] Idle time...lat terminals

dave@umbc3.UMD.EDU (David A Freeman) (05/05/88)

 Hello all,

  Does anyone know how to get the idle time of a LAT terminal?

    Finger uses a kernel mode program called tt_ucb which accesses the 
  unit control block of a terminal, but this won't work for LAT terminals.
  There seems to another level of indirection into LAT that needs to be done. 
  I haven't been able to find anything (useful) out about LAT internals. 
  
  If this is impossible, the idle time of a process would due fine.


					Thanks to all that reply,
					dave



dave@umbc2			bitnet
dave@umbc3.umd.edu		arpa

adelman@Kaos.AI.SRI.COM (Kenneth Adelman) (07/08/88)

> Does anyone know how to get the idle time of a LAT terminal?

    The 'idle' time of a terminal is tranditionally calculated by
subtracting UCB$L_DUETIM (time last I/O was due to complete) from
EXE$GL_ABSTIM (current time). UCB$L_DUETIM is usually set up by
TTDRIVER before calling the hardware port driver to use the VMS device
timeout mechanism to detect hardware failures.

    Not all terminals use this field. In particular, terminals whose
port driver is not directly associated with hardware instruct the
class driver not to do the timeout processing by setting the
TTY$V_PC_NOTIME bit in the UCB$W_PRTCTL field (LAT, Workstation
windows).  Also, DECnet RT terminals do not even go through the normal
TTDRIVER, and RTTDRIVER does not use the DUETIM field.

    The following 'hack', when run during your boot, will:

    1) Link a small piece of code into the port/class interface of
TTDRIVER which updates UCB$L_DUETIM if the device is untimed.

    2) Link a small piece of code into the RTTDRIVER FDT routines
to update UCB$L_DUETIM at the start of each $QIO.

    This code will be invoked when any character is input or output
from your machine, but the overhead should be unmeasurable compared
to the other processing which TTDRIVER must do.

    This program should be run only once during your boot. For it to
patch all of the devices correctly, it must be run AFTER DECnet is
started, but before LAT is started. No promises about VMS V5, but
the code works fine on my VMS V4.7 system.

					    Kenneth Adelman



	.Title	Install-Idle-Monitor
;
;	This loads code into system space and patches into the
;	terminal port/class interface to update UCB$L_ABSTIM whenever
;	a character is sent or received. This allows us to keep
;	track of 'idletime' on non-TIMED devices.
;

	.library /SYS$LIBRARY:LIB/
	$CXBDEF
	$DDTDEF
	$DPTDEF
	$DYNDEF
	$TTYUCBDEF
	$TTYVECDEF
	$UCBDEF

	.Entry	Install_Idle_Monitor,^m<>
	$CMKRNL_S   $$Install_Idle_Monitor
	Ret


	.Entry	$$Install_Idle_Monitor,^m<r2,r3,r4,r5,r6,r7>

	;
	;   See if we have an RTA0 device installed.
	;

	Clrl	R7			; Assume no RTDRIVER DDT to patch
	Jsb	G^Sch$IOLockR		; Lock the I/O database

	MovAQ	RT_DEVICE,R1
	Jsb	G^IOC$SearchDev		; Search for RTA0
	Blbc	R0,1$
	Movl	UCB$L_DDT(R1),R7
1$:

;
;	Allocate a buffer to hold the code the be loaded into
;	nonpaged pool
;

	MovL	#CodeLen+12,R1		; Skip 12 bytes for pool header
	TstL	R7
	BEql	2$
	AddW2	DDT$W_FDTSIZE(R7),R1	; Room for old FDT
	AddW2	#3*4,R1			; Room for the new FDT entry
2$:

	Jsb	G^Exe$AllocBuf
	Blbs	R0,10$
	Pushl	R0
	Brb	Done
10$:

;
;	Copy the code into the pool
;

	MovAB	12(R2),R6		    ; Address of start of code
	MovC3	#CodeLen,W^Code,(R6)	    ; Copy code into pool

;
;	Link the code into the class interface to TTDRIVER.
;

	MovL	G^TTY$GL_DPT,R1		    ; Get TTDRIVER DPT
	MovZWL	DPT$W_VECTOR(R1),R0	    ; Offset to CLASS VECTOR
	AddL2	R0,R1			    ; Address of CLASS VECTOR

	MovL	CLASS_GETNXT(R1),B^V1_Jump-Code(R6)
	MovL	CLASS_PUTNXT(R1),B^V2_Jump-Code(R6)
	MovAB	B^V1-Code(R6),CLASS_GETNXT(R1)
	MovAB	B^V2-Code(R6),CLASS_PUTNXT(R1)

;
;	Build a new FDT routine for RTTDRIVER.
;
	Tstl	R7
	Beql	20$
	Addl3	S^#Patched_RT_FDT-Code,R6,R0; Pointer to start of new FDT
	Movl	DDT$L_FDT(R7),R1	    ; Pointer to start of old FDT
	MovQ	(R1)+,(R0)+		    ; Copy the supported I/O mask
	MovQ	(R1)+,(R0)+		    ; Copy the buffered I/O mask
	MovQ	-16(R1),(R0)+		    ; Copy the supported into the new entry
	MovAB	B^RTT_Fix-Code(R6),(R0)+    ; New FDT code address
	MovZWL	DDT$W_FDTSIZE(R7),R2
	SubL2	#16,R2			    ; Calculate size of remaining FDT
	MovC3	R2,(R1),(R0)		    ; Move it
	MovAL	B^Patched_RT_FDT-Code(R6),DDT$L_FDT(R7)
	AddW2	#12,DDT$W_FDTSIZE(R7)	    ; Update the pointers to the new FDT
20$:
;
;	Exit
;
	Pushl	#SS$_NORMAL
Done:	Movl	G^SCH$GL_CURPCB,R4
	Jsb	G^SCH$IoUnLock
	PopL	R0
	Ret


RT_DEVICE:
	.Ascid	/_RTB0:/

;
;   This code sits in between the port/class interface for each
;   terminal and updates the "DUETIM" field when each I/O occurs
;   It *Must* be PIC.
;
Code:
V1:	BBC	#TTY$V_PC_NOTIME,UCB$W_TT_PRTCTL(R5),10$
	MovL	@#EXE$GL_ABSTIM,UCB$L_DUETIM(R5)
10$:	Jmp	@I^#00000000
V1_Jump = .-4


V2:	BBC	#TTY$V_PC_NOTIME,UCB$W_TT_PRTCTL(R5),10$
	MovL	@#EXE$GL_ABSTIM,UCB$L_DUETIM(R5)
10$:	Jmp	@I^#00000000
V2_Jump = .-4

Rtt_Fix:MovL	@#EXE$GL_ABSTIM,UCB$L_DUETIM(R5)
	Rsb

CodeLen = .-Code

Patched_RT_FDT:

	.End	Install_Idle_Monitor