!TITLE Testing New Subsystems
! This section addressses the practicalities of testing a new subsystem.
! In particular, it draws attention to the difficulties of testing code
! which initially has no access to the terminal I/O procedures and which
! cannot satisfactorily diagnose programming errors (that is, until
! correct operation of the contingency mechanisms has been mastered).
!
! We first describe in more detail the fields in the user record which
! are specially relevant to this situation, namely:
!
! Field DSFI TYPE value
! Base file name 0
! Director version number 8
! Director monitor level 16
! Contingency monitor level 17
! Director monitor filename 19
! Test basefile name 35
!
! Director monitor level and contingency monitor level are cleared to
! zero following an IPL.
!<Test basefile name
! We have stated that "basefile name" specifies the name of the object
! file that is to be entered as the "subsystem", and that the version
! residing on a fixed site on the System disc is used if that name is
! null. If the "test basefile name", is non-null, it overrides the
! setting of "basefile name", even if the latter is null, for the next
! invocation. Thus if the subsystem under test fails disastrously the
! next log-on will yield the default or specified subsystem, which can
! then be used to study the failure and remake the test subsystem.
!>
endoflist
!<Director monitor filename
! The Director monitor filename, if non-null, specifies a file belonging
! to the process owner, into which Director places the following:
! * Process failure messages not diagnosed by the subsystem.
! * Extra monitoring of Director procedure entries (see 'Director
! monitor level'), or extra monitoring of contingencies.
! * Text specified, by the process, to Director procedure DPRINTSTRING
! * The contents of areas of store, printed by DDUMP.
!
! This monitoring file, which must not exceed 512 Kbytes in size, is
! used in a circular manner.
!>
!<Contingency monitor level
! For the case of being unable to satisfy references to Director
! procedures, and for other programming errors not otherwise diagnosable,
! the field "contingency monitor level" will be useful. This
! field is zeroed at IPL, it can be set by a call of Director procedure
! DSFI (TYPE=17). Bits in this word have meanings as follows:
!
! Bit value Meaning and use
! 1 Print a routine trace-back on the occurrence of a
! contingency, with contents of stack frames.
! 2 Print text describing the contingency in words and codes
! ("CLASS/SUBCLASS").
! 4 Print a hexadecimal dump of the stack segment.
! 8 2**3 Print a hexadecimal dump of Director GLA.
! 16 Print the contents of the virtual memory (relating
! segment number to filename and to disc address).
! 32 Print a de-assembly from the code segment of the area
! around the value of the PC register at the time of the
! contingency.
! 64 Print out the machine registers.
!
! A useful value for this field is 99.
!
! In order to diagnose the situation in which a subsystem has been unable
! to satisfy its references to Director procedures, it is useful to have
! a recognisable pattern in the places where the System Call descriptors
! are intended to be placed. With the contingency monitor level 64, that
! pattern will be found in the printing of the machine registers DR0 and
! DR1 if the filling of the System Call descriptor was unsuccessful.
!
! The contingency monitor level field can also be set by typing, at the
! Oper console, a command of the form:
! n/SIGMON m 0
! where n is the process number (as displayed on the Oper screen)
! m is an integer specifying the required value of the field,
! as above.
!>
!<Director monitor level
! If Director monitor level is set non-zero, see SETDIRMON, a
! message is written to Dirlog after each Director procedure called,
! giving the values of the parameters supplied and the result returned.
!>
!<Director version
! A System disc has four fixed sites (256 Kbytes each), for up to four
! versions of Director. Site zero is used by default. Setting the
! Director version field causes the next invocation of the process to use
! the specified Director version (0, 1, 2 or 3) rather than the default
! version (0). This facility should only be used after consultation with
! the System Manager, as the contents of a given Director site cannot
! always be guaranteed to be valid.
!>
list
!<DDUMP
externalroutine DDUMP(integer START, FINISH, CH, LIM)
!
! Prints a hexadecimal dump from virtual address START to virtual address
! FINISH to DIRLOG. The dump has either 16 if LIM = 16, or 32 bytes per
! line.
!>
INTEGER SAVELOGACT, SAME, ADR, J, K, A, L, SAMEAS
STRING (31)ZEROES
SAVELOGACT = LOG ACTION
LOG ACTION = LOG ACTION & (¬DT)
!
START = START & (¬3)
FINISH = FINISH & (¬3)
LIM = 32 UNLESS LIM = 16
!
SAME = 0; ! number of consecutive lines which are the same
ADR = START & (¬(LIM - 1)); ! start of first 'line'
!
WHILE ADR < FINISH CYCLE
K = ADR + LIM - 4; ! useful number
!
A = ADR; ! validation limits
L = LIM
IF ADR < START C
THEN L = L - (START - ADR) AND A = START
IF ADR + LIM > FINISH C
THEN L = L - (ADR + LIM - FINISH)
IF VAL(A, L, 0, 0) = 0 C
THEN WRS("Address Validation Fails") AND -> OUT
!
IF START + LIM <= ADR <= FINISH - LIM START
! at least one whole line before and still to do
SAMEAS = SAME + 1
ZEROES = "ZEROES"
CYCLE J = ADR, 4, K
SAMEAS = 0 AND EXIT UNLESS INTEGER(J-LIM) = INTEGER(J)
ZEROES = "SAME AS ABOVE" UNLESS INTEGER(J) = 0
REPEAT
SAME = SAMEAS
FINISH ELSE SAME = 0
!
IF SAME < 2 START ; ! print address of line
PRINTSTRING("(")
PRHEX(ADR)
PRINTSTRING(") ")
FINISH
!
WRS(ZEROES) IF SAME = 1
!
IF SAME = 0 START
CYCLE J = ADR, 4, K
PRINTSTRING(" ")
IF START <= J < FINISH C
THEN PRHEX(INTEGER(J)) C
ELSE SPACES(8)
REPEAT
SPACES(2)
CYCLE J = ADR, 1, K + 3
CH = 32
IF START <= J < FINISH START
CH = BYTEINTEGER(J)
CH = 32 UNLESS 32 < CH < 126
FINISH
PRINTSYMBOL(CH)
REPEAT
NEWLINE
FINISH
ADR = ADR + LIM
REPEAT
OUT:
LOG ACTION = SAVELOGACT
END ; ! DDUMP
!
!-----------------------------------------------------------------------
!
!<DPRINTSTRING
externalroutine DPRINTSTRING(string (255)S)
!
! Allows a privileged process to write a string to DIRLOG.
!>
PRINTSTRING(S) IF DTRYING << 27 < 0
END ; ! OF DPRINTSTRING
!
!-----------------------------------------------------------------------
!
SYSTEMROUTINE PRINTFL(LONGREAL X,INTEGER A,B)
END ; ! PRINTFL
!
!-----------------------------------------------------------------------
!
ROUTINE PRINTSYMBOL(INTEGER CH)
CONSTINTEGER CH MAX = 655360; ! MAX NO OF CHS TO BE WRITTEN TO DIRLOG BY ONE PROCESS
CONSTINTEGER SPOOL AT BYTES = 60000; ! SPOOLING OF DIRLOG TRIGGERED WHEN NO OF BYTES AVAILABLE EXCEEDS THIS VALUE
CONSTINTEGER SEMANO = (1 << 31) ! 1
!
CONSTINTEGER MAX LINE = 132; ! excluding NL character
OWNSTRING (MAX LINE + 1) LINE
OWNINTEGER LOG I = 1, CH COUNT = 0, SUPPRESS NL = NO
!
STRING (MAX LINE + 1) OUTLINE
INTEGER I, BYTES, LEN, MUST TELL DIRECT, SAVE LOGACT
INTEGER ULOG, DIRLOG, MAINLOG, DAT, USE SEMA, IVE GOT SEMA; ! BOOLEANS
INTEGER SEMADR, J
RECORD (FHDRF)NAME H
RECORD (DIRCOMF)NAME DIRCOM
RECORD (PARMF) P
CH = CH & 255
RETURN IF SUPPRESS NL = YES AND (CH = NL OR CH = ' ')
RETURN UNLESS CH = NL OR 32<= CH <=126
!
SAVE LOGACT = LOG ACTION
DAT = SAVE LOGACT & DT
!
IF LINE = "" START ; ! start of line
SUPPRESS NL = NO
UNLESS DAT = NO C
THEN LINE="DT: ".DATE." ".TIME." ".PROCUSER." ".ITOS(PROCESS)." "
FINISH
!
LINE = LINE.TOSTRING(CH)
LEN = LENGTH(LINE)
IF LEN = MAX LINE START
LINE = LINE.SNL
LEN = LEN + 1
CH = NL
FINISH
RETURN UNLESS CH = NL
!
! Output the string
!
! Move string to allow recursion (for monitor printing)
SUPPRESS NL = YES
OUTLINE = LINE
LINE = ""
ULOG = SAVE LOGACT & WRTOF
DIRLOG = SAVE LOGACT & DLOG
MAINLOG = SAVE LOGACT & LOG
IF DIRLOG#NO AND VAL(DIRLOGAD, DIRLOG KB<<10, W, 0)=0 C
THEN DIRLOG=NO AND MAINLOG = YES
!
! Remove dirlog monitoring to avoid screw-ups over the dirlog semaphore.
LOG ACTION = LOG ACTION & (¬DLOG)
!
! Take sema if appropriate
IVE GOT SEMA = NO
!
*STLN_I
!
IF I >> 18 = SIG STACK SEG OR DIRLOG = NO C
THEN USE SEMA = NO C
ELSE USE SEMA = YES
!
IF USE SEMA = YES AND GOT SEMA = NO START
DIRCOM == RECORD(SYSAD(DIRCOM KEY, -1))
SEMADR = ADDR(DIRCOM_DIRLOGSEMA)
J = PP(SEMADR, SEMANO,"PRINTSYMBOL")
IVE GOT SEMA = YES IF J=0
FINISH
!
! Move string to appropriate destinations
J = STRING TO FILE(LEN, ADDR(OUTLINE)+1, FILE1AD) UNLESS ULOG = NO
J = STRING TO FILE(LEN, ADDR(OUTLINE)+1, DIRLOGAD) UNLESS DIRLOG = NO
!
UNLESS MAINLOG = NO START
CYCLE J = 1, 1, LEN
CH = CHARNO(OUTLINE, J)
BYTEINTEGER(OUTPAD + LOG I) = CH
IF LOG I = 31 OR CH = NL START
BYTEINTEGER(OUTPAD) = LOG I
*OUT_1
LOG I = 1
FINISH ELSE LOG I = LOG I + 1
REPEAT
FINISH
!
! Is DIRLOG full enough to require spooling?
MUST TELL DIRECT = NO
UNLESS DIRLOG = NO START
H == RECORD(DIRLOGAD)
BYTES = H_NEXT CYCLIC - H_READ TO
IF BYTES < 0 C
THEN BYTES = BYTES + (H_NEXT FREE BYTE - H_TXT REL ST)
IF BYTES > SPOOL AT BYTES AND H_SEMA = 0 START
MUST TELL DIRECT = YES
H_SEMA = -1; ! to show that SOMEONE is telling DIRECT
FINISH
CH COUNT = CH COUNT + LEN
IF CH COUNT > CH MAX AND PROCESS # 1 START
SAVE LOGACT = SAVE LOGACT & (¬DLOG)
DOPER2("TOO MUCH OUTPUT")
FINISH
FINISH
IF IVE GOT SEMA = YES THEN VV(SEMADR, SEMANO)
IF MUST TELL DIRECT = YES START
P = 0
P_DEST = X'FFFF0028'
J = DPON3I("DIRECT", P, 0, 1, PON AND CONTINUE)
FINISH
LOG ACTION = SAVE LOGACT
END ; ! PRINTSYMBOL
!
!-----------------------------------------------------------------------
!
EXTERNALROUTINE PRHEX(INTEGER I)
PRINTSTRING(HTOS(I,8))
END ; ! PRHEX
!
!-----------------------------------------------------------------------
!
EXTERNALROUTINE PREC(STRING (255)S, RECORD (PARMF)NAME P, INTEGER N)
INTEGER A,I
PRINTSTRING(S)
A = ADDR(P)
CYCLE I = 0, 4, 28
PRHEX(INTEGER(A + I))
SPACE
REPEAT
NEWLINE IF N = 0
END ; ! OF PREC
!
!-----------------------------------------------------------------------
!
SYSTEMROUTINE WRITE(INTEGER I,PL)
INTEGER SIGN
STRING (31) S
SIGN = ' '
IF I<0 START
SIGN = '-'
IF I=X'80000000' THEN I=X'7FFFFFFF' ELSE I=-I
FINISH
S=ITOS(I)
IF LENGTH(S)<PL THEN SPACES(PL-LENGTH(S))
PRINTSYMBOL(SIGN)
PRINTSTRING(S)
END ; ! WRITE
!
!-----------------------------------------------------------------------
!
SYSTEMROUTINE IOCP(INTEGER EP,N)
INTEGER NUM,SYM,J
!%CONSTSTRING(15)%ARRAY IM(0:17)= %C
! 'INVALID',
! 'READSYMBOL',
! 'NEXTSYMBOL',
! 'PRINTSYMBOL',
! 'READCH',
! 'PRINTCH',
! 'RECONSTRUCT',
! 'PRINTSTRING',
! 'SELECTINPUT',
! 'SELECTOUTPUT',
! 'ISO CARD',
! 'CHOP CUR OUT',
! 'SET INMARG',
! 'SET OUTMARG',
! 'SET READ ADDR',
! 'PRINTSTRING',
! 'CLOSE STREAM',
! 'MULSYMBOL'
SWITCH IO(0:17)
EP=0 UNLESS 0<EP<=17
-> IO(EP)
IO(3): ! PRINTSYMBOL(N)
IO(5): ! PRINTCH(N)
PRINTSYMBOL(N)
RETURN
IO(7): ! PRINTSTRING
IO(15): ! PRINTSTRING (ONLY VALID CHARS ALLOWED)
J=0; NUM=BYTEINTEGER(N)
WHILE J<NUM CYCLE
J=J+1
PRINTSYMBOL(BYTEINTEGER(N+J))
REPEAT
RETURN
IO(17): ! MULSYMBOL
NUM=(N>>8) & 255
SYM=N&255
J=0
WHILE J<NUM CYCLE
PRINTSYMBOL(SYM)
J=J+1
REPEAT
RETURN
IO(0):
IO(1):IO(2):IO(4):IO(6):IO(8):IO(9):
IO(10):IO(11):IO(12):IO(13):IO(14):IO(16):
WRSN("ILLEGAL CALL ON IOCP, EP =", EP)
END ; ! IOCP
!
!-----------------------------------------------------------------------
!
EXTERNALROUTINE SYMBOLS(INTEGER N, SYMBOL)
IF 0 < N < 256 AND 0 <= SYMBOL < 256 C
THEN IOCP(17, (N << 8) ! SYMBOL)
END
!
!
!<SETDIRMON
! %externalroutine SETDIRMON(%string(255)S)
!
! If S is null or is the single character '0', Director monitoring is
! switched off, else it is switched on. When monitoring is on, a record
! is written to Dirlog for each Director procedure called giving the
! parameters used and its result.
!>
!
!-------------------end-of-included-text---------------------------------
!