%IF %DECLARED(FTSIG) %THEN %IF NOT(FTSIG) %THEN %ERROR('INTR.BLI with FTSIG off??') %FI %ELSE LITERAL FTSIG=1 %FI; !To trigger conditional compilation FIELD INT_FIELDS=SET !INTERRUPT block fields DFF[INT$PISYS,0,0,36,0], !PISYS. block starts here DFF[INT$WHAT,0,0,36,0], !Device or non-I/O condition DFF[INT$CONDITION,0,0,36,0], !synonym DFF[INT$OFFSET,1,18,18,0], !Offset within interrupt vector DFF[INT$REASONS,1,0,18,0], !Reasons for I/O interrupt, as follows: DFF[INT$IN_DONE,1,16,1,0], !Input done DFF[INT$OUT_DONE,1,15,1,0], !Output done DFF[INT$EOF,1,14,1,0], !End of File DFF[INT$IN_ERROR,1,13,1,0], !Input Error DFF[INT$OUT_ERROR,1,12,1,0], !Output Error DFF[INT$OFFLINE,1,11,1,0], !Device went off-line DFF[INT$FULL,1,10,1,0], !Device Full DFF[INT$QUOTA_EX,1,9,1,0], !Quota exceeded DFF[INT$IO_WAIT,1,8,1,0], !I/O Wait DFF[INT$ONLINE,1,7,1,0], !Device On-line !DFF[INT$ZERO,2,0,36,0], !Spare word in PISYS. block MUST BE 0 DFF[INT$PROCESS,3,0,18,0], !Process that owns this interrupt DFF[INT$NEXT,4,0,18,0], !Next interrupt in chain for process DFF[INT$S_REASONS,4,18,18,0], !Signal associated condition if these occur DFF[INT$S_ALWAYS,4,18,1,0], !Signal always DFF[INT$S_ALLIO,4,25,10,0], !All I/O conditions DFF[INT$S_IN_DONE,4,34,1,0], !Input done DFF[INT$S_OUT_DONE,4,33,1,0], !Output done DFF[INT$S_EOF,4,32,1,0], !End of File DFF[INT$S_IN_ERROR,4,31,1,0], !Input error DFF[INT$S_OUT_ERROR,4,30,1,0], !Output error DFF[INT$S_OFFLINE,4,29,1,0], !Device went offline DFF[INT$S_FULL,4,28,1,0], !No more room DFF[INT$S_QUOTA_EX,4,27,1,0], !Quota exceeded DFF[INT$S_IO_WAIT,4,26,1,0], !I/O wait DFF[INT$S_ONLINE,4,25,1,0], !Device came online DFF[INT$PENDING,5,35,1,0], !This block has a pending SIGNAL already DFF[INT$TEMP,5,34,1,0], !This block is temporary (delete it when done) DFF[INT$SIGNAL_ARGS,5,0,18,0], !If non-zero, condition to signal DFF[INT$CODE,6,0,36,0], !First signal argument, fields within follow DFF[INT$SEVERITY,6,0,3,0], !Warning/Error/Fatal error/Success DFF[INT$SUCCESS,6,0,1,0], !TRUE bit, success bit DFF[INT$STSCODE,6,3,22,0], !Status code DFF[INT$FACCODE,6,25,11,0], !Facility code DFF[INT$STATUS,7,0,36,0], !Status word from vector block DFF[INT$PC,8,0,36,0], !PC that interrupt happened at DFF[INT$REASON,9,0,18,0], !Reason for interrupt (I/O interrupts only) DFF[INT$R_IN_DONE,9,16,1,0], !Input done DFF[INT$R_OUT_DONE,9,15,1,0],!Output done DFF[INT$R_EOF,9,14,1,0], !End of File DFF[INT$R_IN_ERROR,9,13,1,0],!Input Error DFF[INT$R_OUT_ERROR,9,12,1,0],!Output Error DFF[INT$R_OFFLINE,9,11,1,0], !Device went off-line DFF[INT$R_FULL,9,10,1,0], !Device Full DFF[INT$R_QUOTA_EX,9,9,1,0], !Quota exceeded DFF[INT$R_IO_WAIT,9,8,1,0], !I/O Wait DFF[INT$R_ONLINE,9,7,1,0], !Device On-line DFF[INT$FILBLK,9,18,18,0] !File block for device TES; LITERAL INT_LEN=10; !Minimum length of interrupt block MACRO INT_BLOCK=BLOCK[INT_LEN] FIELD(INT_FIELDS) %; FIELD INTVEC_FIELDS=SET !Fields in the interrupt vector blocks DFF[INTVEC$NEWPC,0,0,36,0], !Usually points to [CALL INTSIG(INTBLK)] DFF[INTVEC$OLDPC,1,0,36,0], !PC where it happened DFF[INTVEC$REASON,2,0,18,0],!What kind of I/O condition was it? DFF[INTVEC$RID,2,16,1,0], !Input done DFF[INTVEC$ROD,2,15,1,0], !Output done DFF[INTVEC$IODONE,2,15,2,0], !I/O done (sum of the previous 2) DFF[INTVEC$REF,2,14,1,0], !End of File DFF[INTVEC$EOF,2,14,1,0], ! " " DFF[INTVEC$RIE,2,13,1,0], !Input Error DFF[INTVEC$ROE,2,12,1,0], !Output Error DFF[INTVEC$IOERR,2,12,2,0],!I/O Error DFF[INTVEC$RDO,2,11,1,0], !Device went off-line DFF[INTVEC$OFFLINE,2,11,1,0],! " " DFF[INTVEC$RDF,2,10,1,0], !Device Full DFF[INTVEC$RQE,2,9,1,0], !Quota exceeded DFF[INTVEC$RWT,2,8,1,0], !I/O Wait DFF[INTVEC$RON,2,7,1,0], !Device came on-line DFF[INTVEC$ONLINE,2,7,1,0],! " " DFF[INTVEC$ERROR,2,9,5,0], !I/O error, dev full or Quota ex or offline DFF[INTVEC$FLAGS,2,18,18,0],!Control flags as follows DFF[INTVEC$VPO,2,34,1,0], !Disable all interrupts on interrupt DFF[INTVEC$VTO,2,33,1,0], !Disable until DEBRK. DFF[INTVEC$VAI,2,32,1,0], !Don't disable even this block (do not set) DFF[INTVEC$VDS,2,31,1,0], !Dismiss additional interrupts DFF[INTVEC$VPM,2,30,1,0], !Print standard message if any DFF[INTVEC$VIP,2,29,1,0], !Interrupt in progress (clear on restart) DFF[INTVEC$STATUS,3,0,36,0] !Status word TES; STRUCTURE INTVECSTR[I,O,P,S,E;N]= [N*4] (INTVECSTR+I+O); MACRO IOWAIT(INT,COND)= BEGIN MAP INT: REF INT_BLOCK; INT[INT$S_ALWAYS]=-1; !Set all the error signal bits INT[%NAME(INT$S_,COND)]=0; !If it wasn't what we're waiting for,error. WAIT(.INT) END%; MACRO BUILD_LIST (ARGLST)[ARG]=ARGLST[%COUNT]=ARG %; MACRO COND_LST=FREG<18,18> %; !LH of FREG MACRO ESTABLISH(RTN)= !Must be before first executable statement!! STACKLOCAL ARGLST: VECTOR[%LENGTH+1]; BUILD_LIST (ARGLST,RTN,%LENGTH-1,%REMAINING); COND_LST=ARGLST; !Handler now established % ; MACRO INTERRUPTS(FLAGS,BLOCK)=PISYS(%NAME(PISYSF_,FLAGS),BLOCK) %; LITERAL PISYSF_OFF=%O'200000', PISYSF_ON=%O'100000', PISYSF_CLEAR=%O'40000', PISYSF_CLEARDEV=%O'20000', PISYSF_REMOVE=%O'10000', PISYSF_ADD=%O'4000', PISYSF_ON_ADD=%O'104000', !Turn on & add device PISYSF_REMOVEC=PISYSF_REMOVE+PISYSF_CLEARDEV; !Field defs for SIGNAL_ARGS FIELD SA_FIELDS= SET DFF[SA$LENGTH,FIRSTWORD,WRD], !Length of argument block DFF[SA$CODE,NEXTWORD,WRD], !Condition code DFF[SA$SEVERITY,THISWORD,SEVERITY], !Severity field DFF[SA$STSCODE,THISWORD,STSCODE], !code describing error DFF[SA$FACCODE,THISWORD,FACCODE], !Facility code DFF[SA$STATUS,NEXTWORD,WRD], !Status info from interrupt DFF[SA$FORK,THISWORD,WRD], !Fork that is aborting DFF[SA$FB,THISWORD,WRD], !FILE BLOCK FOR errors but not interrupts DFF[SA$PC,NEXTWORD,WRD], !PC from interrupt DFF[SA$QUIT_CODE,THISWORD,WRD], !abort code as follows DFF[SA$QUIT_STSCODE,THISWORD,STSCODE], !Reason process aborted DFF[SA$QUIT_SEVERIT,THISWORD,SEVERITY], !Severity indicator DFF[SA$QUIT_FACCODE,THISWORD,FACCODE], !Facility code DFF[SA$REASON,NEXTWORD,RH], !Reason for interrupt DFF[SA$IN_DONE,THISWORD,16,1,0], !Input done DFF[SA$OUT_DONE,THISWORD,15,1,0], !Output done DFF[SA$EOF,THISWORD,14,1,0], !End of File DFF[SA$IN_ERROR,THISWORD,13,1,0], !Input Error DFF[SA$OUT_ERROR,THISWORD,12,1,0], !Output Error DFF[SA$OFFLINE,THISWORD,11,1,0], !Device went off-line DFF[SA$FULL,THISWORD,10,1,0], !Device Full DFF[SA$QUOTA_EX,THISWORD,9,1,0], !Quota exceeded DFF[SA$IO_WAIT,THISWORD,8,1,0], !I/O Wait DFF[SA$ONLINE,THISWORD,7,1,0], !Device On-line DFF[SA$FILBLK,THISWORD,LH] !File block for interrupts TES; LITERAL !Offsets for SIGNAL_ARGS SA_LENGTH=0, !Length of argument block SA_CODE=1, !What happened SA_STATUS=2, SA_PC=3, SA_REASON=4; LITERAL !Offsets for MECHANISM_ARGS MA_LENGTH=0, MA_FRAME=1, MA_DEPTH=2, MA_VREG=4, MA_T2=5, MA_T3=6, MA_T4=7, MA_T5=8, MECH_ARGS_LEN=8; MACRO $CODE= BLOCK[.SIGNAL_ARGS,SA$STSCODE]%, $SEVERITY=BLOCK[.SIGNAL_ARGS,SA$SEVERITY]%, $FACCODE=BLOCK[.SIGNAL_ARGS,SA$FACCODE]%; MACRO SIGNAL[]= BEGIN %IF NOT %DECLARED (%NAME('.SIGNL')) %THEN EXTERNAL %NAME('.SIGNL'); %FI LOCAL SIGNAL_ARGS: VECTOR[%LENGTH+1]; BUILD_LIST(SIGNAL_ARGS,%LENGTH,%REMAINING); %NAME('.SIGNL')(SIGNAL_ARGS); END; %; LITERAL SS$_CONTINUE=1; !Handler wants to continue LITERAL SS$_RESIGNAL=0; !Handler passes the buck LITERAL SS$_UNWIND=8; !Facility code for UNWIND condition !Process block offsets FIELD PROCESS_FIELDS=SET DFF[P$NEXT,0,0,18,0], !Next process to run DFF[P$LINK,0,18,18,0], !Next process at this level or 0 DFF[P$STKL,1,18,18,0], !Length of stack DFF[P$STK,1,0,18,0], !Address of stack DFF[P$WAIT,2,0,36,0], !If non-zero, what process is waiting for DFF[P$INTERRUPTS,3,0,18,0], !Head of signal chain for process DFF[P$FREE,3,18,18,0], !How much storage to free when cleaning up DFF[P$SUPERIOR,4,0,18,0], !Process who created this one DFF[P$INFERIORS,4,18,18,0], !Pointer to linked list of inferiors DFF[P$NAME,5,0,36,0], !Name of process DFF[P$NDB,6,0,18,0], !NDB for process, if any DFF[P$DISPLAY,6,18,18,0] !Routine to call to display more stuff TES; LITERAL P_LEN=7; MACRO PROCESS_BLOCK=BLOCK[P_LEN] FIELD(PROCESS_FIELDS) %; %( FIELD STACK_FIELDS=SET DFF[S$SREG,3,0,36,0], !Stored SREG DFF[S$FREE,17,0,36,0] !First free location on stack TES; MACRO STACK=BLOCK[STACK_LENGTH] FIELD(STACK_FIELDS) %; )% LITERAL STACK_LENGTH=1024; MACRO FORK(RTN)[]= BEGIN LOCAL V: REF PROCESS_BLOCK; EXTERNAL ROUTINE CPROC; LOCAL ARGLST: VECTOR[%LENGTH]; BUILD_LIST(ARGLST,%LENGTH-1,%REMAINING); !Build argument list V=CPROC(RTN,ARGLST,STACK_LENGTH); V[P$NAME]=%SIXBIT %STRING(RTN); .V END%; MACRO WAKESET(IB)[REASON]=IB[%NAME(INT$,REASON)]=1%, ERRSET(IB)[REASON]=IB[%NAME(INT$,REASON)]=IB[%NAME(INT$S_,REASON)]=1%; MACRO NOINTS[]= BEGIN LOCAL NOINTS_VAL; !Value of block EXTERNAL INTENC; INTERRUPTS(OFF); INTENC=.INTENC+1; NOINTS_VAL=(%REMAINING); IF (INTENC=.INTENC-1) LEQ 0 THEN INTERRUPTS(ON); .NOINTS_VAL END%; !System-dependant macro to represent name of process MACRO PNAME(NAM)=%SIXBIT %STRING(NAM) %;