cdc:nos2.source:opl871:smfex
Table of Contents
SMFEX
Table Of Contents
- [00004] SCREEN MANAGEMENT FACILITY EXECUTIVE.
- [00360] INITBITMAP - INITIALIZE A BIT MAP ARRAY.
- [00390] BUILDTASK - ALLOCATE FIELD LENGTH AND INIT POINTERS.
- [00484] GENWRKNAM - GENERATE WORKFILE NAME FOR THIS USER.
- [00506] ADDVECT - ADD DATA INTO A STATISTICS VECTOR.
- [00679] GETUSER - MAKE TABLE ENTRIES ACCESSIBLE FOR CURRENT USER.
- [00703] PUTUSER - PRESERVE TABLE ENTRIES IN DENSE TABLE.
- [00727] GETCOMMON - GET STORAGE FOR RIGHT TASK INTO COMMON.
- [00769] PUTCOMMON - COPY COMMON INTO DISPATCHING AREA.
- [00793] KILL - ERASE USE FROM TABLES.
- [00819] SCHEDULE - ASSURE USER WILL RUN IN A TASK SOON.
- [00850] PUTINQ - PUT CURRENT USER IN SCHEDULE QUEUE.
- [00899] TAKEOFFQ - TAKE CURRENT USER OFF QUEUE.
- [00961] ALLOC - ALLOCATE RESOURCE VIA BITMAP.
- [00992] DEALLOC - UPDATED BITMAP TO MAKE RESOURCE AVAILABLE.
- [01020] FORCEALLOC - ALLOCATE SPECIFIC RESOURCE WITHOUT SEARCH.
- [01050] KILLECSBITS - FORCEALLOC ALL ECS SWAP PAGES.
- [01068] PURGETTI - GET RID OF ANY TERMINAL INPUT CHAINS.
- [01099] DROPSLICE - RECALL CPU FOR A LITTLE WHILE.
- [01118] DOTIMER - SUPERVISE TIME DEPENDENCIES.
- [01219] DOOPER - PERFORM OPERATOR FUNCTIONS.
- [01296] DOINPUT - ACCEPT MESSAGES FROM IAFEX.
- [01617] RUNJOBS - SUPERVISE TASK EXECUTION.
- [01933] INSTRUMENT - TAKE STATISTICS.
- [02087] SMFDLY - INTERFACE FOR TASKS TO DELAY.
- [02110] SMFRCL - INTERFACE FOR TASKS TO AUTO-RECALL ON AN EVENT.
- [02140] CLEARINT - ACKNOWLEGE USER BREAK.
- [02165] CLEARQUE - ATTEMPT TO CLEAR TASKREQUE FLAG.
- [02194] SPINWHEELS - DELAY TASK UNTIL INPUT ARRIVES.
- [02218] OKTOWAIT - COMPUTE RULES FOR SPINWHEELS.
- [02262] FATALTRAP - INTERFACE FOR FAILING TASKS.
- [02285] ABTPAUSE - TRY TO CHECKPOINT WORKFILE AFTER ABORT.
- [02305] ABTKILL - KILL OFF TASK AFTER DOUBLE ABORT.
- [02334] BGNMETER - INSTRUMENT BEGINNING OF EDIT SESSION.
- [02350] WIOSTAT - WORKIO STATISTICS INTERFACE.
- [02370] RTRNWRKFIL - RETURN THE WORKFILE FNT.
- [02397] SENDLOGOUT - TRANSMIT LAST OUTPUT AND ROLLIN SINGLE.
- [02439] TRANSMIT - TRANSMIT A FUNCTION CODE/MESSAGE TO IAFEX.
- [02554] VOLUNTEER - SEE IF THIS TASK SHOULD SLOW DOWN.
- [02688] TTITRAP - PROVIDE EDITOR CODE WITH INPUT TEXT.
- [02883] TTOTRAP - QUEUE/ISSUE OUTPUT, SWAP AS NEEDED.
- [03025] SWAP - SWAP THIS TASK IN OR OUT.
- [03191] PAUSE - INTERFACE TO EXECUTIVE TO START/END TIME SLICE.
- [03212] TRANSACT - TRANSITION FROM EXECUTIVE TO USER FOR SWAPIN.
- [03301] ENDTRANS - END A TRANSACTION WITH SWAPOUT.
- [03355] INITMON - INITIALIZE SMFEX.
- [03617] TERMMON - TERMINATE SMFEX NORMALLY.
- [03630] MELT - TERMINATE SMFEX ABNORMALLY.
- [03664] MAIN ALGORITHM.
Source Code
- SMFEX.txt
- PRGM SMFEX;
- BEGIN
- #
- ** SMFEX - SCREEN MANAGEMENT FACILITY EXECUTIVE.
- *
- * COPYRIGHT CONTROL DATA SYSTEMS INC. 1992.
- *
- * THE SMFEX PROGRAM IS THE EXECUTIVE OR MONITOR FOR THE SMFEX
- * SUBSYSTEM. THE FUNCTION PROVIDED BY THE SMFEX SUBSYSTEM IS
- * AN ALTERNATE IMPLEMENTATION OF THE FULL SCREEN EDITOR (FSE)
- * TO BE MEMORY RESIDENT, SERVICING LARGE USER COMMUNITIES
- * WITH A REDUCTION IN SYSTEM SCHEDULING OVERHEAD COMPARED TO
- * THE CONVENTIONAL EXECUTION OF A UNIQUE JOB FOR EACH USER.
- *
- * THE SMFEX PROGRAM IS RESPONSIBLE TO MANAGE THE
- * MULTI-TASKING TECHNIQUE WHICH ALLOWS THE EDITOR CODE TO BE
- * SHARED BY MULTIPLE USERS. THE EDITOR CODE RESIDES IN
- * SEVERAL SOURCE MODULES OUTSIDE OF THIS PROGRAM. SMFEX AND
- * THE EDITING MODULES ARE COMBINED BY THE LOADER. EDITING
- * MODULES REQUIRE SEPARATE COMPILATION WITH CERTAIN
- * MODIFY-TIME DEFINITIONS CHANGED TO YIELD TWO SETS OF
- * RELOCATABLE MODULES, ONE SUITABLE FOR LOADER PROCESSING TO
- * YIELD FSE AND THE OTHER SUITABLE FOR LOADER PROCESSING TO
- * YIELD SMFEX.
- *
- #
- DEF LISTCON #1#;
- CONTROL PRESET; # UNIVERSAL DEFINITIONS #
- *CALL COMFMLT
- *CALL COMFFSE
- # SMFEX'S OWN DEFS #
- *CALL COMFSMF
- # SIC CODES. IAFEX TALKS TO OUR BUFFER 0, SINGLE-USER FSE TALKS #
- # TO OUR BUFFER 1 WITH A DIFFERENT SET OF CODES. #
- STATUS IAF2SMF
- INIT,
- MSGIN,
- OUTDONE,
- BREAK,
- HUNGUP,
- CONNECT;
- STATUS SMF2IAF
- INIT,
- MSGOUT,
- PROMPT,
- LOGOUT;
- STATUS TASKST
- EMPTY,
- DELAY,
- RECALLFET,
- START,
- SWAP,
- RUN,
- PRELIM;
- # TYPES OF STATISTICS COLLECTED #
- STATUS INSTST
- THNK,
- RSPNS,
- NOTTI,
- NOTASK,
- SWPE,
- SWPD,
- CLOCKTICK,
- PREEMPT,
- SWPTIM,
- EDTCIO,
- SESSION,
- TRANS,
- XSTTO,
- BREAKS,
- HANGUPS,
- BGNEDT,
- ENDEDT,
- INPUT,
- XMIT,
- KWIKTOC,
- TASKUTIL,
- WORKIO,
- DROPCPU;
- DEF MOD4(ZZ) #((ZZ) LAN 3)#;
- DEF MOD8(ZZ) #((ZZ) LAN 7)#;
- DEF MOD32(ZZ) #((ZZ) LAN 31)#;
- PAGE # EXTERNAL REF'S AND DEF'S #
- XDEF
- BEGIN
- PROC SMFRCL; PROC SMFDLY;
- PROC CLEARINT; PROC VOLUNTEER;
- PROC TTITRAP; PROC TTOTRAP;
- PROC FATALTRAP; PROC CLEARQUE;
- CONTROL IFEQ METERING,1;
- PROC BGNMETER;
- PROC WIOSTAT;
- CONTROL FI;
- ARRAY RENTSTK [1:MAXREENT]; # SUBROUTINE STACK #
- BEGIN
- ITEM RSTK;
- END
- ITEM RSTKPTR;
- END
- XREF PROC MOVEWD;
- XREF
- BEGIN
- # FIRST COME COMPASS ROUTINES, FOR SPECIAL/OPTIMAL TRICKS #
- FUNC FINDBIT; FUNC NOSWDSZ;
- PROC SPREAD; PROC GATHER;
- PROC FLDLEN; PROC FLDLENE;
- PROC SFMSSTF; PROC SFMCSTF; PROC TESTECS;
- PROC READECS; PROC WRITECS;
- PROC GETUTAB; PROC SAVUTAB;
- # NOW COME THE STANDARD UOI SYMPLIB ROUTINES WE NEED #
- PROC WRITEO; PROC READO;
- PROC RECALL; PROC SYSREQ;
- PROC READ; PROC READC;
- PROC REWIND; PROC STATUSP;
- PROC WRITER; PROC REWRITR;
- PROC WRITEC; PROC WRITEW;
- PROC MESSAGE; PROC DISTCON;
- PROC RETERN; PROC GETFLCE;
- PROC ONSW; PROC RTIME;
- PROC SETRFLE; PROC PROTEON;
- PROC EVICT;
- PROC FILINFO; PROC REQUEST; PROC EESET;
- PROC ENDRUN; PROC ABORT;
- # NOW COME ENTRIES TO FSE EDITOR #
- FUNC MIN; FUNC MAX;
- PROC PROCESS; PROC EDTINIT; PROC MAKEFET; PROC EDTTERM;
- PROC PAUSEIO; PROC RESUMIO; PROC CHECKIO;
- PROC TTSYNC; PROC FATAL;
- PROC VDSYNCH;
- END
- PAGE # COMMON DATA AREAS #
- *CALL COMFDS1
- *CALL COMFVD2
- *CALL COMFDS2
- PAGE # EDITOR TABLES #
- # COMPILED HERE ONLY FOR CONTROL PRESET #
- *CALL COMFTAB
- PAGE # SMFEX'S OWN DATA #
- ITEM TIMEOFDAY=0;
- ITEM SLICECOUNT=0;
- ITEM OLDTIMEDAY=0;
- ITEM NEWTIMEDAY=0;
- ITEM IDLEDOWN B=FALSE;
- ITEM STOPNOW B=FALSE;
- ITEM ACCEPTNONE B=FALSE;
- ITEM ECSDOWN B=FALSE;
- ITEM SHUTDOWN=0; # CONTROLS OPERATOR SHUTDON #
- ITEM COMPLETE B=FALSE; # USED TO SHUT WHOLE THING DOWN #
- ITEM CURUSER; # UTILITY VARIABLE #
- ITEM CURTASK; # CURRENT TASK REFERENCE #
- ITEM LASTTASK=0; # PREVIOUS TASK TO RUN #
- ITEM TASKSAVAIL=3; # TASKS CURRENTLY AVAILABLE/IN USE #
- ITEM TASKSBUSY=0; # NUMBER OF TASKS IN USE NOW #
- ITEM CHNGSTATUS; # CURRENT TASKS CHANGE OF STATUS #
- ITEM REMAINTTI=NUMTTIBUF; # HOW MANY BUFFERS AVAIL #
- ITEM DISPATLEN; # LENGTH OF DISPATCHED DATA SEGMENT #
- ITEM SWAPLEN; # LENGTH OF SWAPPED SEGMENT #
- ITEM SWAPPRUS; # LENGTH SWAPPED IN PRU COUNT #
- ITEM SWAPBUFLEN; # LENGTH SWAP CIRCULAR BUFFS #
- ITEM MAXSWPPAG=0; # HIGHEST (DISK ONLY) SWAP PAGE USED #
- ITEM MODELPTR; # POINTS TO COPY OF VIRGIN DATA #
- ITEM MODELLEN; # LENGTH OF VIRGIN COMMON COPY #
- ITEM FIELDLEN;
- ITEM LOGGEDIN=0;
- ITEM WRKFILLOCK B=FALSE;
- ITEM ENABLEFLAG=0;
- CONTROL IFEQ METERING,1;
- ITEM MAXLOGGED=0;
- ITEM STATTIME=0;
- CONTROL FI;
- CONTROL IFEQ ECSCODE,1;
- ITEM ECSFIELD=0;
- ITEM ECSERRORS=0;
- CONTROL FI;
- ITEM STATUSMSG C(30)="0000 USERS 00 TASKS";
- BASED ARRAY ANYFET;;
- BASED ARRAY MOVFROM;;
- BASED ARRAY MOVTO;;
- ARRAY TTICONTROL [1:NUMTTIBUF];
- BEGIN
- ITEM TTICTLWORD = [NUMTTIBUF(0)];
- ITEM TTIBUFLEN U(0,0,12);
- ITEM TTIBUFLNK U(0,12,12);
- ITEM TTIBUFADDR U(0,42,18);
- END
- ARRAY SWAPBITS (NUMSWPBIT);;
- ARRAY TTIBITS (NUMTTIBIT);;
- ARRAY SWAPGOOD (NUMSWPBIT);;
- ARRAY SWAPBAD (NUMSWPBIT);;
- ARRAY TTIGOOD (NUMTTIBIT);;
- BASED ARRAY SWAPMASK;;
- # NOTE THAT CURUSERTAB MUST MATCH USERTAB, WORD BY FIELD. #
- # NOTE ALSO THAT THE FORMATS OF THESE ARRAYS ARE HARDCODED #
- # IN THE COMPASS SUBROUTINES GETUTAB AND SAVUTAB. #
- ARRAY CURUSERTAB (22);
- BEGIN
- ITEM CURUSLOGGED B(0)=[FALSE];
- ITEM CURUSINQUE B(1)=[FALSE];
- ITEM CURUSDROP B(02)=[FALSE]; # CURRENT USER DROP FLAG #
- ITEM CURUSDONE B(3)=[FALSE];
- ITEM CURUSINTASK B(4)=[FALSE];
- ITEM CURUSSTART B(5)=[FALSE];
- ITEM CURUSINTRPT B(6)=[FALSE];
- ITEM CURUSCRUNCH B(7)=[FALSE];
- ITEM CURUSLOSTDT B(8)=[FALSE];
- ITEM CURUSRCVRY B(9)=[FALSE];
- ITEM CURUSOLDSND B(10)=[FALSE];
- ITEM CURUSVICTIM B(11)=[FALSE];
- ITEM CURUSSTMWRK B(12)=[FALSE];
- ITEM CURUSOKOUT B(13)=[FALSE];
- ITEM CURUSSTKPTR (14)=[0];
- ITEM CURUSTASK (15)=[0];
- ITEM CURUSTTIBUF (16)=[0];
- ITEM CURUSQUELNK (17)=[0];
- ITEM CURUSIAFNUM (18)=[0];
- ITEM CURUSFNTPTR (19)=[0];
- ITEM CURUSSWPPAG (20)=[0];
- ITEM CURUSLASTIM (21)=[0];
- END
- # NOTE COMMENTS ABOVE ON RESTRICTIONS AGAINST REDEFINITION #
- # OF EITHER CURUSERTAB OR USERTAB. #
- ARRAY USERTAB [1:NUMSMFUSR] S(3);
- BEGIN
- ITEM USERWORD0 (0)=[NUMSMFUSR(0)];
- ITEM USERWORD1 (1)=[NUMSMFUSR(0)];
- ITEM USERWORD2 (2)=[NUMSMFUSR(0)];
- ITEM USERFLAGS U(0,0,18);
- ITEM USERLOGGED B(0,0,1); # IS LOGGED FULLY IN #
- ITEM USERINQUE B(0,1,1); # ALREADY IN SWAPIN QUEUE #
- ITEM USERDROP B(00,02,01); # USER DROPPED PHONE CONNECT #
- ITEM USERDONE B(0,3,1); # EDIT HAS COMPLETED #
- ITEM USERINTASK B(0,4,1); # ASSIGNED TO SOME TASK #
- ITEM USERSTART B(0,5,1); # ONLY FOR RIGHT AFTER LOGGED #
- ITEM USERINTRPT B(0,6,1); # WE MUST SOON SERVICE BREAK KEY #
- ITEM USERCRUNCH B(0,7,1); # USER IS FILE-CRUNCHING,LOW PRIO #
- ITEM USERLOSTDT B(0,8,1); # USER LOST EXCESS INPUT DATA #
- ITEM USERRCVRY B(0,9,1); # SWAPPING IN ONLY TO CHKPT #
- ITEM USEROLDSND B(0,10,1); # MIDDLE OF SERIES OF SENDS #
- ITEM USERVICTIM B(0,11,1); # VICTIMIZED BY SMFEX ECS ERROR #
- ITEM USERSTMWRK B(0,12,1); # USE STIMULATION WRKFIL NAME #
- ITEM USEROKOUT B(0,13,1); # O.K. TO PRODUCE TTY OUTPUT #
- ITEM USERSTKPTR U(0,18,6); # REENTRANCY STACK LEVEL #
- ITEM USERTASK U(0,24,6); # WHICH TASK ARE WE IN #
- ITEM USERTTIBUF U(0,30,6); # WHICH INPUT BUFFER WE OWN #
- ITEM USERQUELNK U(0,36,12); # LINKAGE IN SWAP QUEUE #
- ITEM USERIAFNUM U(0,48,12); # WHICH IAFEX PORT #
- ITEM USERFNTPTR U(1,0,12); # TO SPEED UP CIO'S #
- ITEM USERSWPPAG U(1,12,12); # WHICH SWAP PAGE #
- ITEM USERLASTIM U(1,24,30); # LAST TIME STAMP #
- ITEM USERJSN C(2,0,4); # JOB SEQUENCE NUMBER #
- ITEM USEREJT U(2,24,12); # JOB EJT ORDINAL #
- END
- ARRAY TASKTAB [1:NUMTASKS] P(13);
- BEGIN
- ITEM TASKSTATUS (0)=[0]; # CURRENT TASK STATUS #
- ITEM TASKFLAGS (1)=[0]; # ALL BITS OFF #
- ITEM TASKREQUE B(1,0,1); # USER NEEDS REPEATED SERVICE #
- ITEM TASKABORT B(1,2,1); # TASK IS ABORTING #
- ITEM TASKSWPNOW B(1,3,1); # CURRENTLY EXECING SWAP CODE #
- ITEM TASKSWPIN B(1,4,1); # DIRECTION OF SWAP IS IN #
- ITEM TASKUSER (2)=[0]; # WHICH USER IN THIS TASK #
- ITEM TASKNXTTTO (3)=[0]; # WHERE TO APPEND NEXT OUTPUT #
- ITEM TASKTYPTTO (4)=[0]; # TRANSMIT CODE DESIRED #
- ITEM TASKRCLADR (5)=[0]; # CURRENT RECALL FET #
- ITEM TASKADDR (6)=[0]; # ADDRESS OF TASK MEMORY #
- ITEM TASKSTKPTR (7)=[0]; # DISPATCHING RSTKPTR #
- ITEM TASKDSPADR (8)=[0]; # DISPATCH DATA START #
- ITEM TASKTIME (9)=[0]; # TIMEOFDAY SWAPPED IN #
- ITEM TASKSWPFIL (10)=[0]; # WHICH SWAP FILE IN USE #
- ITEM TASKSWPPRU (11)=[0]; # WHICH PRU IN THAT FILE #
- ITEM TASKPULSE (12)=[0]; # FAKE FET FOR CLOCK EVENTS #
- END
- ARRAY SWAPQ (3);
- BEGIN
- ITEM SWPQHEAD I(0)=[0];
- ITEM SWPQTAIL I(1)=[0];
- ITEM SWPQSIZE I(2)=[0];
- END
- ARRAY SSCINPUT [-1:O"100"]; ITEM SSCINP (0)=[O"102"(0)];
- ARRAY IAFMSGWORD;
- BEGIN
- ITEM IAFHEADER; # WHOLE WORD #
- ITEM IAFFUNC U(0,0,12)=[SMF2IAF"INIT"];
- ITEM IAFTERM U(0,12,12)=[0];
- ITEM IAFPTR U(0,24,18)=[0];
- ITEM IAFLEN U(0,42,18)=[1];
- END
- ARRAY INITSSC [0:1]; ITEM INITSSCWORD=[0,0];
- BASED ARRAY SSCBUFFER;
- BEGIN
- ITEM SSCWORD;
- ITEM SSCCOUNT U(0,36,6);
- ITEM SSCTYPE U(0,46,2);
- ITEM SSCSTATUS U(0,48,12);
- END
- ARRAY NULLFET(FETSIZ); ITEM NULLFETDT C(1,0,2);
- ARRAY SWPFETS [1:NUMSWPFET] S(FETSIZ);
- BEGIN
- ITEM SWPFET;
- ITEM SWPFETDONE B(0,59,1);
- ITEM SWPFETDT C(1,0,2);
- ITEM SWPFETR B(1,12,1);
- ITEM SWPFETL U(1,36,6);
- ITEM SWPFETIN U(2,42,18);
- ITEM SWPFETOUT U(3,42,18);
- ITEM SWPFETCRI U(6,0,30);
- ITEM SWPFETW B(6,30,1);
- ITEM SWPFETRR U(6,31,29);
- END
- ARRAY DMBFET(FETSIZ);;
- ARRAY FILINFPARMS (5);
- BEGIN
- ITEM FILINFNAME C(0,0,7);
- ITEM FILINFLENC U(0,42,18)=[O"050001"];
- ITEM FILINFSTAT U(1,12,42);
- ITEM FILINFTTY B(1,43,1);
- ITEM FILINFRMS B(1,44,1);
- ITEM FILINFWRIT B(1,52,1);
- ITEM FILINFREAD B(1,53,1);
- ITEM FILINFFT U(1,54,6);
- END
- PAGE # MINOR UTILITY ROUTINES #
- PROC INITBITMAP(MAP,NUMWORD,NUMBIT);
- BEGIN
- #
- ** INITBITMAP - INITIALIZE A BIT MAP ARRAY.
- *
- * INITBITMAP PREPARES BITMAPS FOR USAGE. A BIT MAP CONSISTS
- * OF ANY NUMBER OF WORDS, EACH CONTAINING A 32-BIT MASK.
- * THE MASK IS POSITIONED 12 BITS RIGHT FROM THE SIGN BIT OF
- * THE WORD. THIS FORMAT ALLOWS SEARCHING FOR BITS WHICH ARE
- * STILL ON BY INSERTING A FLOATING POINT EXPONENT AND
- * EXECUTING THE NORMALIZE INSTRUCTION.
- *
- * ENTRY MAP - THE MAP TO INITIALIZE.
- * NUMWORD - HOW MANY WORDS IN THE MAP.
- * NUMBIT - HOW MANY TOTAL BITS IN THE MAP.
- *
- * EXIT MAP - SETUP.
- *
- * CALLS FORCEALLOC.
- #
- ARRAY MAP[0:999]; ITEM MAPWORD;
- ITEM NUMWORD, NUMBIT;
- ITEM TMP1;
- FOR TMP1=0 STEP 1 UNTIL NUMWORD-1 DO MAPWORD[TMP1]
- =O"00007777777777600000";
- FOR TMP1=NUMBIT+1 STEP 1 UNTIL NUMWORD*32
- DO FORCEALLOC(MAP,TMP1,NUMWORD);
- END # OF INITBITMAP #
- PROC BUILDTASK(WHICH);
- BEGIN
- #
- ** BUILDTASK - ALLOCATE FIELD LENGTH AND INIT POINTERS.
- *
- * BUILDTASK ALLOCATES FIELD LENGTH FOR PER-TASK ARRAYS, AND
- * MAPS OUT THE BASE ADDRESSES FOR THE ARRAYS. BUILDTASK THEN
- * COPIES THE SET OF POINTERS INTO THE TASK'S DISPATCHING AREA.
- *
- * ENTRY WHICH - TASK NUMBER.
- * FIELDLEN - CURRENT TOP OF FIELD LENGTH.
- *
- * EXIT FIELDLEN - INCREASED.
- * TASKSPADR[WHICH] - ADDRESS OF TASK DISPATCH AREA.
- * TASK DISPATCH AREA - SETUP.
- *
- * CALLS FLDLEN, MOVEWD.
- *
- * USES POINTER WORDS FOR FOLLOWING ARRAYS -
- * ARRAYEND, ARRAYSTART, AUDITSTAGE, BACKSTACK,
- * BACKSTORE, BFPRU, CHGSTRING1, DISK, DISPRSTK,
- * FET, FKEYDEFS, LINEBUF, LOCSTRING1, LOCSTRING2,
- * MOVTO, OBF, READLIST, ROWCONTROL, SPLITCONTROL,
- * SWAPRSTK, TITLE1LIN, TITLE2LIN, TTOBUFFER.
- *
- * NOTE THIS CODE AND THE ARRAY LAYOUT IN COMFDAT ARE
- * EXTREMELY INTERDEPENDENT.
- #
- ITEM WHICH;
- TASKADDR[WHICH]=FIELDLEN;
- # FIRST ALLOCATE EDITOR ARRAYS, ORDER AND SIZE MATCHING COMFDAT #
- P<ARRAYSTART>=FIELDLEN;
- FIELDLEN=FIELDLEN+1;
- P<TABLEHEADR> = FIELDLEN;
- FIELDLEN = FIELDLEN + 6; # *TDU* TABLE LENGTH #
- P<TABLEWORDS> = FIELDLEN;
- FIELDLEN = FIELDLEN + O"272"; # *TDU* TABLE LENGTH #
- P<SPLITCONTROL>=FIELDLEN;
- FIELDLEN=FIELDLEN+2*SPLTCTLSIZ;
- P<ROWCONTROL>=FIELDLEN;
- FIELDLEN=FIELDLEN+2*(MAXROWS+1);
- P<BACKSTACK>=FIELDLEN;
- FIELDLEN=FIELDLEN+(BACKMAX+1);
- P<BACKSTORE>=FIELDLEN;
- FIELDLEN=FIELDLEN+(2*(TEMPIND+1));
- P<FKEYDEFS>=FIELDLEN;
- FIELDLEN=FIELDLEN+NUMFKEYS;
- P<AUDITSTAGE>=FIELDLEN;
- FIELDLEN=FIELDLEN+AUDITSIZE+1;
- P<LOCSTRING1>=FIELDLEN;
- FIELDLEN=FIELDLEN+STRWID;
- P<LOCSTRING2>=FIELDLEN;
- FIELDLEN=FIELDLEN+STRWID;
- P<CHGSTRING1>=FIELDLEN;
- FIELDLEN=FIELDLEN+STRWID;
- P<FKEYSTRINGS>=FIELDLEN;
- FIELDLEN=FIELDLEN+(2*NUMFKEYS);
- P<FKEYNUMB>=FIELDLEN;
- FIELDLEN=FIELDLEN+POSFKEYS;
- P<TITLE1LIN>=FIELDLEN;
- FIELDLEN=FIELDLEN+TTLLNLEN+1;
- P<TITLE2LIN>=FIELDLEN;
- FIELDLEN=FIELDLEN+TTLLNLEN+1;
- P<ARRAYEND>=FIELDLEN;
- FIELDLEN=FIELDLEN+1;
- # END OF ALLOCATED EDITOR ARRAYS #
- # ALLOCATE BUFFERS AND CONTROL VECTORS #
- P<BFPRU>=FIELDLEN;
- FIELDLEN=FIELDLEN+BUFSIZE;
- P<SWAPRSTK>=FIELDLEN;
- FIELDLEN=FIELDLEN+MAXREENT;
- TASKDSPADR[WHICH]=FIELDLEN;
- FIELDLEN=FIELDLEN+DISPATLEN;
- P<DISPRSTK>=FIELDLEN;
- FIELDLEN=FIELDLEN+MAXREENT;
- P<TTOBUFFER>=FIELDLEN;
- FIELDLEN=FIELDLEN+SIZTTOBUF+2;
- P<FET>=FIELDLEN;
- FIELDLEN=FIELDLEN+FETSIZ;
- P<OBF>=FIELDLEN;
- FIELDLEN=FIELDLEN+OBFSIZE;
- P<DISK>=FIELDLEN;
- FIELDLEN=FIELDLEN+DSKSIZ;
- P<READLST>=FIELDLEN;
- FIELDLEN=FIELDLEN+LSTSIZE;
- FLDLEN(FIELDLEN+4);
- P<LINEBUF>=LOC(LIN);
- P<MOVTO>=TASKDSPADR[WHICH];
- MOVEWD(DISPATLEN,DATASTART,MOVTO);
- END # OF BUILDTASK #
- PROC GENWRKNAM;
- BEGIN
- #
- ** GENWRKNAM - GENERATE WORKFILE NAME FOR THIS USER.
- *
- * GENWRKNAM DETERMINES THE CORRECT FILENAME FOR THE WORK-
- * FILE FOR THE CURRENT USER. THE FILE NAME IS UNIQUE FOR
- * EACH USER AND IS GENERATED BY THE USER'S TLX CALL TO
- * CONNECT TO SMFEX, AND IS EQUAL TO "WK" PLUS JSN.
- *
- * ENTRY CURUSIAFNUM - IAF TERMINAL NUMBER.
- * USERJSN[CURUSER] - JSN OF THE USER'S JOB.
- *
- * EXIT WORKNAM - CORRECT NAME.
- #
- C<0,2>WORKNAM="WK";
- C<2,4>WORKNAM=USERJSN[CURUSER];
- C<6,1>WORKNAM=0;
- END # OF GENWRKNAM #
- CONTROL IFEQ METERING,1;
- PROC ADDVECT(VECTOR,DATA);
- BEGIN
- #
- ** ADDVECT - ADD DATA INTO A STATISTICS VECTOR.
- *
- * ADDVECT IS PART OF THE INSTRUMENTATION FEATURE OF SMFEX
- * AND SERVES TO INCREMENT THE TOTALS AND ONE VALUE-DEPENDENT
- * COUNTER IN A SELECTED VECTOR. THE VECTOR HAS ONE WORD FOR
- * TOTAL VALUE AND TOTAL EVENT COUNT, THEN FOUR WORDS EACH
- * CONTAINING FOUR 15-BIT COUNTERS. THE COUNTER TO BE
- * INCREMENTED IS SELECTED BY THE DATA VALUE, WITH THE FIRST
- * COUNTER FOR VALUES OF ZERO, THE SECOND FOR VALUES OF ONE,
- * AND THE THIRD THRU SIXTEENTH COUNTER CORRESPONDING TO
- * VALUES IN THE RANGE (2**(N-2)) .LE. VALUE .LT. (2**(N-1)).
- *
- * ENTRY DATA - VALUE TO RECORD.
- *
- * EXIT VECTOR - UPDATED.
- #
- ITEM TMP1, TMP2, TMP3 R;
- ARRAY VECTOR[0:4]; ITEM WORD;
- ITEM DATA;
- B<0,30>WORD[0]=B<0,30>WORD[0]+DATA;
- B<30,30>WORD[0]=B<30,30>WORD[0]+1;
- IF DATA LQ 0 THEN TMP1=0;
- ELSE
- BEGIN
- TMP3=DATA*1.0;
- TMP1=B<6,6>TMP3-15;
- END
- TMP1=MAX(TMP1,0);
- TMP1=MIN(TMP1,15);
- TMP2=MOD4(TMP1)*15;
- TMP1=(TMP1/4)+1;
- IF B<TMP2,15>WORD[TMP1] NQ O"77777"
- THEN B<TMP2,15>WORD[TMP1]=B<TMP2,15>WORD[TMP1]+1;
- END # OF ADDVECT #
- CONTROL FI;
- PAGE # TRACE ROUTINES FOR DEBUG #
- DEF TCTL # CONTROL IFEQ TRACEFLAG,1; #;
- DEF TRCOUT(AA) # TCTL TRACEOUT(AA); CONTROL FI #;
- DEF TRCSTR(AA) # TCTL TRACESTR(AA); CONTROL FI #;
- DEF TRCDEC(AA) # TCTL TRACEDEC(AA); CONTROL FI #;
- DEF TRCFRC # TCTL TRACEFRC; CONTROL FI #;
- DEF TRCWORDS(AA,BB) # TCTL TRACEWORDS(AA,BB); CONTROL FI #;
- DEF TRCBOTH(AA,BB) # TCTL TRACEBOTH(AA,BB); CONTROL FI #;
- CONTROL IFEQ TRACEFLAG,1;
- PROC TRACEOUT(TEXT);
- BEGIN
- ARRAY TEXT[0:99]; ITEM TXTWORD;
- ITEM INITED B=FALSE;
- ARRAY TRCFET (FETSIZ);;
- ARRAY TRCLIN[0:20]; ITEM TRCLINE;
- ITEM TRCPTR,TXTPTR;
- ARRAY TRCBUFF [0:O"2000"];;
- IF NOT INITED THEN
- BEGIN
- INITED=TRUE;
- TRCPTR=0;
- MAKEFET(TRCFET,"TRACE",TRCBUFF,O"2001");
- END
- TXTPTR=0;
- TRCLINE[TRCPTR]=TXTWORD[TXTPTR];
- WHYLE B<48,12>TXTWORD[TXTPTR] NQ 0 DO
- BEGIN
- TXTPTR=TXTPTR+1;
- TRCPTR=TRCPTR+1;
- TRCLINE[TRCPTR]=TXTWORD[TXTPTR];
- END
- FOR TXTPTR=9 STEP -1 WHILE TXTPTR GQ 0
- AND C<TXTPTR,1>TRCLINE[TRCPTR] EQ ":"
- DO C<TXTPTR,1>TRCLINE[TRCPTR]=" ";
- TRCPTR=TRCPTR+1;
- TRCLINE[TRCPTR]=0;
- IF TRCPTR GQ 07 THEN
- BEGIN
- WRITEC(TRCFET,TRCLIN);
- TRCPTR=0;
- END
- RETURN;
- ENTRY PROC TRACEWORDS(TEXT,NWORDS);
- ITEM NWORDS;
- IF NOT INITED THEN
- BEGIN
- INITED=TRUE;
- TRCPTR=0;
- MAKEFET(TRCFET,"TRACE",TRCBUFF,O"2001");
- END
- IF TRCPTR NQ 0 THEN
- BEGIN
- WRITEC(TRCFET,TRCLIN);
- TRCPTR=0;
- END
- WRITEW(TRCFET,TEXT,NWORDS);
- IF B<48,12>TXTWORD[NWORDS-1] NQ 0 THEN WRITEW(TRCFET,0,1);
- RETURN;
- ENTRY PROC TRACEFRC;
- IF TRCPTR NQ 0 THEN
- BEGIN
- WRITEC(TRCFET,TRCLIN);
- TRCPTR=0;
- END
- WRITER(TRCFET,1);
- END # OF TRCOUT #
- PROC TRACESTR(STR);
- BEGIN
- ITEM STR C(40);
- ARRAY TEXT [0:4]; ITEM TXTWORD;
- ITEM TMP1;
- TXTWORD[0]=0;
- FOR TMP1=0 STEP 1 WHILE TMP1 LQ 39 AND C<TMP1,1>STR NQ "$" DO
- BEGIN
- C<MOD(TMP1,10),1>TXTWORD[TMP1/10]=C<TMP1,1>STR;
- TXTWORD[1+TMP1/10]=0;
- END
- TRCOUT(TEXT);
- END # OF TRCSTR #
- PROC TRACEDEC(NUM);
- BEGIN
- ITEM NUM;
- ITEM TMP1,TMP2,TMP3;
- TMP1=NUM;
- TMP2=O"55555555555555330000";
- TMP3=7;
- IF TMP1 LS 0 THEN
- BEGIN
- C<0,1>TMP2="-";
- TMP1=-TMP1;
- END
- WHYLE TMP1 NQ 0 DO
- BEGIN
- C<TMP3,1>TMP2=O"33"+MOD(TMP1,10);
- TMP3=TMP3-1;
- TMP1=TMP1/10;
- END
- TRCOUT(TMP2);
- END # OF TRCDEC #
- PROC TRACEBOTH(AA,BB);
- BEGIN
- ARRAY AA;;
- ARRAY BB;;
- TRCSTR(AA);
- TRCDEC(BB);
- END # OF TRCBOTH #
- CONTROL FI;
- PAGE # UTIITIES FOR QUEUES, CHAINS, TABLES #
- PROC GETUSER;
- BEGIN
- #
- ** GETUSER - MAKE TABLE ENTRIES ACCESSIBLE FOR CURRENT USER.
- *
- * GETUSER UNPACKS THE DENSELY FORMATTED, INDEXABLE USER
- * TABLE INTO THE SPARSE, NONINDEXABLE USER TABLE. THE DENSE
- * TABLE PROVIDES CONSERVATION OF MEMORY CAPACITY, WHILE
- * THE SPARSE TABLE PROVIDES CONSERVATION OF CODE SIZE AND
- * TIMING FOR FREQUENT REFERENCES.
- *
- * ENTRY CURUSER - INDEX FOR WHICH USER.
- * USERTAB[CURUSER] - "DENSE PACK" FORMATTED TABLE.
- *
- * EXIT CURUSERTAB - EXPANDED COPY OF USERTAB.
- *
- * CALLS GETUTAB.
- #
- BASED ARRAY PARM;;
- P<PARM>=LOC(USERTAB[CURUSER]);
- GETUTAB(PARM,CURUSERTAB);
- END # OF GETUSER #
- PROC PUTUSER;
- BEGIN
- #
- ** PUTUSER - PRESERVE TABLE ENTRIES IN DENSE TABLE.
- *
- * PUTUSER IS CALLED TO COPY AND PACK THE SPARSELY FORMATTED,
- * NON-INDEXABLE USER TABLE INTO THE DENSELY FORMATTED,
- * INDEXABLE TABLE. PUTUSER IS THUS THE OPPOSITE OF
- * GETUSER. NOTE THAT THE SPARSE TABLE IS TEMPORARY AND
- * THE DENSE TABLE IS PERMANENT.
- *
- * ENTRY CURUSER - CURRENT USER.
- * CURUSERTAB - SPARSE TABLE.
- *
- * EXIT USERTAB[CURUSER] - PACKED VERSION OF TABLE.
- *
- * CALLS SAVUTAB.
- #
- BASED ARRAY PARM;;
- P<PARM>=LOC(USERTAB[CURUSER]);
- SAVUTAB(PARM,CURUSERTAB);
- END # OF PUTUSER #
- PROC GETCOMMON;
- BEGIN
- #
- ** GETCOMMON - GET STORAGE FOR RIGHT TASK INTO COMMON.
- *
- * TO CONSERVE CPU TIME REQUIRED FOR SHUFFLING OF THE COMMON
- * BLOCK IN MULTI-TASKING, THE COMMON BLOCK IS LEFT VOLATILE
- * WHEN ONE TASK GIVES UP THE CPU IN THE HOPE THAT THE SAME
- * TASK WILL BE THE NEXT TO USE THE CPU. WHEN A DIFFERENT
- * TASK IS NEXT ON THE CPU, THEN WE MUST PERFORM THE DEFERRED
- * COPYING OF COMMON TO/FROM TASK DISPATCHING AREAS.
- *
- * ENTRY LASTTASK - TASK WHICH MOST RECENTLY USED COMMON.
- * ZERO INDICATES COMMON IS NOT VOLATILE.
- * CURTASK - TASK WHICH NEEDS COMMON.
- * TASKSWPNOW[LASTTASK], TASKSWPIN[LASTTASK] -
- * INDICATE IF VOLATILITY SUPPRESSED BY
- * CURRENTLY ACTIVE SWAPIN.
- *
- * EXIT LASTTASK - EQUALS CURTASK.
- * COMMON BLOCK - SAVED IN LASTTASK IF NEEDED,
- * UPDATED FOR CURTASK IF NEEDED.
- *
- * CALLS MOVEWD.
- *
- * USES P<MOVFROM>, P<MOVTO>.
- #
- IF LASTTASK NQ 0 AND LASTTASK NQ CURTASK AND
- NOT (TASKSWPNOW[LASTTASK] AND TASKSWPIN[LASTTASK]) THEN
- BEGIN
- P<MOVTO>=TASKDSPADR[LASTTASK];
- MOVEWD(DISPATLEN,DATASTART,MOVTO);
- END
- IF LASTTASK NQ CURTASK THEN
- BEGIN
- P<MOVFROM>=TASKDSPADR[CURTASK];
- MOVEWD(DISPATLEN,MOVFROM,DATASTART);
- END
- LASTTASK=CURTASK;
- END # OF GETCOMMON #
- PROC PUTCOMMON;
- BEGIN
- #
- ** PUTCOMMON - COPY COMMON INTO DISPATCHING AREA.
- *
- * PUTCOMMON IS CALLED WHEN THE LIVE COMMON BLOCK IS CONSIDERED
- * MORE CURRENT THAN THE COMMON IMAGE IN THE TASK DISPATCHING
- * AREA, AND REQUIRES IMMEDIATE COPYING.
- *
- * ENTRY CURTASK - CURRENT TASK.
- * TASKDSPADR[CURTASK] - ADDRESS OF DISPATCH AREA.
- *
- * EXIT DISPATCH AREA - UPDATED FROM DATASTART.
- *
- * CALLS MOVEWD.
- *
- * USES P<MOVTO>.
- #
- # COPY DISPATCHABLE STORAGE FOR THIS TASK OUT OF COMMON #
- P<MOVTO>=TASKDSPADR[CURTASK];
- MOVEWD(DISPATLEN,DATASTART,MOVTO);
- END # OF PUTCOMMON #
- PROC KILL;
- BEGIN
- #
- ** KILL - ERASE USE FROM TABLES.
- *
- * KILL IS CALLED WHEN DISCONNECTING A USER. IT IS ASSUMED
- * THE USER IS NOT IN THE SWAPIN QUEUE. THE USER MAY
- * HAVE TERMINAL INPUT BUFFERS, WHICH ARE RELEASED. THEN
- * THE TABLE ENTRIES ARE ZEROED.
- *
- * ENTRY CURUSER - WHO TO KILL.
- * CURUSIAFNUM - IAF TERMINAL NUMBER.
- *
- * EXIT USERTAB[CURUSER], ORDWORD[CURUSIAFNUM] - ZERO.
- * CURUSERTAB - ZERO ALSO.
- *
- * CALLS PURGETTI, PUTUSER, GETUSER.
- #
- PURGETTI;
- USERWORD0[CURUSER]=0;
- USERWORD1[CURUSER]=0;
- USERWORD2[CURUSER]=0;
- GETUSER;
- END # OF KILL #
- PROC SCHEDULE;
- BEGIN
- #
- ** SCHEDULE - ASSURE USER WILL RUN IN A TASK SOON.
- *
- * SCHEDULE IS USED WHENEVER WE RECEIVE A CODE FROM IAFEX,
- * ASSURES THE USER WILL BE SCHEDULED FOR TASK SERVICE OR WILL
- * BE ADEQUATELY SERVICED IF ALREADY IN A TASK.
- *
- * ENTRY CURUSER - USER TO BE QUEUED.
- * CURUSERTAB - ALL ENTRIES SETUP.
- * CURUSINTASK - WHETHER ALREADY SCHEDULED.
- * CURUSINQUE - WHETHER ALREADY QUEUED.
- * CURUSTASK - WHICH TASK IF CURUSINTASK TRUE.
- *
- * EXIT USER QUEUED IF NOT ALREADY IN TASK.
- * TASKREQUE[] - SET IF IN TASK TO SIGNAL EVENT.
- * TASKPULSE[] - SET TO QUICKLY END ANY DELAY.
- *
- * CALLS PUTINQ.
- #
- IF CURUSINTASK THEN
- BEGIN
- TASKREQUE[CURUSTASK]=TRUE; # ASSURE KEEPS RUNNING #
- TASKPULSE[CURUSTASK]=3; # ASSURE NO CLOCK DELAY LOOP #
- END
- ELSE IF NOT CURUSINQUE THEN PUTINQ;
- END # OF SCHEDULE #
- PROC PUTINQ;
- BEGIN
- #
- ** PUTINQ - PUT CURRENT USER IN SCHEDULE QUEUE.
- *
- * PUTINQ LINKS THE CURRENT USER ONTO THE QUEUE OF JOBS
- * WHICH HAVE BEEN SCHEDULED FOR FUTURE TASK ASSIGNMENT.
- * A NEW QUEUE LINKAGE IS STARTED IF THERE IS NO QUEUE
- * ALREADY.
- *
- * ENTRY CURUSER - CURRENT USER.
- * CURUSERTAB - ALL ENTRIES SETUP.
- * CURUSINQUE - MUST BE FALSE.
- * SWPQHEAD - ZERO IF NO QUEUE EXISTS, OR LINK TO HEAD
- * OF QUEUE IF OTHER USERS ALREADY QUEUED.
- * SWPQTAIL - IF SWPQHEAD NON-TRIVIAL, LAST USER QUEUED.
- * SWPQSIZE - NUMBER OF USERS IN QUEUE.
- *
- * EXIT VIA MELT IF INVALID CONDITIONS.
- * SWPQHEAD - HEAD OF QUEUE. (CURUSER IF NEW QUEUE)
- * SWPQTAIL - TAIL OF QUEUE NOW EQUALS CURUSER.
- * USERQUELNK[OLD SWPQTAIL] - LINKS TO CURUSER IF THERE
- * WAS A PREVIOUS QUEUE.
- * CURUSINQUE - TRUE.
- * SWPQSIZE - INCREMENTED.
- *
- * CALLS MELT.
- #
- CONTROL IFGQ PARANOIA,5;
- IF CURUSINQUE THEN MELT("PUTINQ 1$");
- CONTROL FI;
- IF SWPQHEAD EQ 0 THEN # NEW QUEUE #
- BEGIN
- SWPQHEAD=CURUSER;
- SWPQTAIL=CURUSER;
- CURUSQUELNK=0;
- END
- ELSE # APPEND TO QUEUE #
- BEGIN
- USERQUELNK[SWPQTAIL]=CURUSER;
- CURUSQUELNK=0;
- SWPQTAIL=CURUSER;
- END
- CURUSINQUE=TRUE;
- SWPQSIZE=SWPQSIZE+1;
- END # OF PUTINQ #
- PROC TAKEOFFQ;
- BEGIN
- #
- ** TAKEOFFQ - TAKE CURRENT USER OFF QUEUE.
- *
- * TAKEOFFQ REMOVES THE CURRENT USER FROM THE QUEUE OF USERS
- * SCHEDULED FOR FUTURE TASK ASSIGNMENT. THE CURRENT USER IS
- * REQUIRED TO BE IN THE QUEUE, BUT IS ALLOWED TO BE AT THE
- * HEAD, OR AT THE TAIL, OR ANYWHERE IN BETWEEN. TAKEOFFQ
- * THEREFORE CONTAINS LOGIC TO CLOSE QUEUE LINKAGE UP AROUND
- * THE EXTRACTED USER.
- *
- * ENTRY CURUSER - CURRENT USER.
- * CURUSERTAB - ALL ENTRIES SETUP.
- * CURUSINQUE - MUST BE TRUE.
- * SWPQHEAD - HEAD OF QUEUE.
- * SWPQTAIL - TAIL OF QUEUE.
- * SWPQSIZE - NUMBER OF USERS IN QUEUE.
- * USERQUELNK[ALL IN QUEUE] - LINKAGE.
- *
- * EXIT CURUSINQUE - FALSE.
- * CURUSQUELNK - ZEROED OUT.
- * SWPQTAIL - BACKED TO PREVIOUSLY NEXT-TO-LAST
- * USER IF CURUSER MATCHED SWPQTAIL.
- * SWPQHEAD - ADVANCED TO PREVIOUSLY SECOND USER IF
- * CURUSER MATCHED SWPQHEAD. ZERO IF CURUSER WAS
- * ONLY USER IN QUEUE.
- * SWPQSIZE - DECREMENTED.
- *
- * CALLS MELT.
- #
- ITEM TMP1,TMP2;
- CONTROL IFGQ PARANOIA,5;
- IF NOT CURUSINQUE THEN MELT("TAKEOFFQ 1$");
- CONTROL FI;
- IF SWPQHEAD EQ CURUSER THEN # TAKE FROM FRONT #
- BEGIN
- IF SWPQHEAD EQ SWPQTAIL THEN SWPQTAIL=0;
- SWPQHEAD=CURUSQUELNK;
- END
- ELSE # FIND THEN EXTRACT #
- BEGIN
- TMP1=SWPQHEAD;
- WHYLE TMP1 NQ CURUSER DO
- BEGIN
- CONTROL IFGQ PARANOIA,5;
- IF TMP1 EQ 0 THEN MELT("TAKEOFFQ 2$");
- CONTROL FI;
- TMP2=TMP1;
- TMP1=USERQUELNK[TMP1];
- END
- IF TMP1 EQ SWPQTAIL THEN SWPQTAIL=TMP2;
- USERQUELNK[TMP2]=USERQUELNK[TMP1];
- END
- CURUSINQUE=FALSE;
- CURUSQUELNK=0;
- SWPQSIZE=SWPQSIZE-1;
- END # OF TAKEOFFQ #
- PROC ALLOC(BITMAP,BITMASK,INDEX,LIMIT);
- BEGIN
- #
- ** ALLOC - ALLOCATE RESOURCE VIA BITMAP.
- *
- * SEARCH THE BITMAP FOR AN AVAILABLE ENTITY, RETURN THE INDEX
- * FOR IT. SET THE BIT AS UNAVAILABLE. BITMAPS ARE 32-BITS
- * PER WORD, CENTERED, SO THAT THE FINDBIT ROUTINE CAN USE
- * OPTIMAL INSTRUCTIONS (E.G., NORMALIZE) TO FIND A BIT. A
- * BIT IS ON TO SHOW AVAILABLE ENTITY.
- *
- * ENTRY BITMAP - THE BITMAP ARRAY TO SEARCH AND UPDATE.
- * BITMASK - ARRAY WITH "DONT USE" FLAGS.
- * LIMIT - SIZE OF ARRAYS.
- *
- * EXIT INDEX - ORDINAL OF ALLOCATED RESOURCE.
- * BITMAP - UPDATED TO REFLECT ALLOCATION.
- *
- * CALLS FINDBIT.
- #
- ARRAY BITMAP[0:99]; ITEM BITWORD;
- ARRAY BITMASK;;
- ITEM INDEX, LIMIT;
- INDEX=FINDBIT(LIMIT,BITMAP,BITMASK);
- IF INDEX NQ -1 THEN B<12+MOD32(INDEX),1>BITWORD[INDEX/32]=0;
- INDEX=INDEX+1; # ADJUST TO ORIGIN OF ONE #
- END # OF ALLOC #
- PROC DEALLOC(BITMAP,INDEX,LIMIT);
- BEGIN
- #
- ** DEALLOC - UPDATED BITMAP TO MAKE RESOURCE AVAILABLE.
- *
- * DEALLOC IS THE COUNTERPART TO ALLOC.
- *
- * ENTRY BITMAP - ARRAY CONTAINING ALLOCATION FLAGS.
- * INDEX - WHICH RESOURCE TO FREE UP.
- * LIMIT - SIZE OF BITMAP.
- *
- * EXIT BITMAP - UPDATED.
- *
- * CALLS MELT.
- #
- ITEM INDEX, LIMIT;
- ARRAY BITMAP [0:99]; ITEM BITWORD;
- ITEM TMP1;
- TMP1=INDEX-1;
- CONTROL IFGQ PARANOIA,5;
- IF TMP1 GQ LIMIT*32 OR TMP1 LS 0 THEN MELT("DEALLOC 1$");
- IF B<12+MOD32(TMP1),1>BITWORD[TMP1/32] EQ 1
- THEN MELT("DEALLOC 2$");
- CONTROL FI;
- B<12+MOD32(TMP1),1>BITWORD[TMP1/32]=1;
- END # OF DEALLOC #
- PROC FORCEALLOC(BITMAP,INDEX,LIMIT);
- BEGIN
- #
- ** FORCEALLOC - ALLOCATE SPECIFIC RESOURCE WITHOUT SEARCH.
- *
- * FORCES A BIT AS UNAVAIL. USED TO CUT OFF EXCESS BITS AT
- * END OF A BITMAP AND TO SHUT OFF ENTITIES THAT HAVE SUFFERED
- * HARDWARE FAILURES. (SUCH AS SEGMENTS OF ECS)
- *
- * ENTRY BITMAP - ARRAY OF ALLOCATION FLAGS.
- * INDEX - WHICH RESOURCE TO ALLOCATE.
- * LIMIT - SIZE OF BITMAP.
- *
- * EXIT BITMAP - UPDATED.
- *
- * CALLS MELT.
- #
- ITEM INDEX,LIMIT;
- ARRAY BITMAP[0:99]; ITEM BITWORD;
- ITEM TMP1;
- TMP1=INDEX-1;
- CONTROL IFGQ PARANOIA,5;
- IF TMP1 GQ LIMIT*32 OR TMP1 LS 0 THEN MELT("FORCEALLOC 1$");
- CONTROL FI;
- B<12+MOD32(TMP1),1>BITWORD[TMP1/32]=0;
- END # OF FORCEALLOC #
- PROC KILLECSBITS(BITMAP);
- BEGIN
- #
- ** KILLECSBITS - FORCEALLOC ALL ECS SWAP PAGES.
- *
- * ENTRY BITMAP - ARRAY OF ALLOCATION FLAGS TO UPDATE.
- *
- * BITMAP - UPDATED.
- *
- * CALLS FORCEALLOC.
- #
- ARRAY BITMAP;;
- ITEM TMP1;
- FOR TMP1=1 STEP 1 UNTIL NUMSWPECS
- DO FORCEALLOC(BITMAP,TMP1,NUMSWPBIT);
- END # OF KILLECSBITS #
- PROC PURGETTI;
- BEGIN
- #
- ** PURGETTI - GET RID OF ANY TERMINAL INPUT CHAINS.
- *
- * ENTRY CURUSER - CURRENT USER.
- * CURUSTTIBUF - FIRST TTI BUFFER OR NULL.
- * REMAINTTI - HOW MANY BUFFERS STILL AVAIL.
- * TTIBUFLNK[ALL] - LINKAGES.
- * TTIBITS - ALLOCATION BITMASK.
- *
- * EXIT CURUSTTIBUF - NULL.
- * REMAINTTI - INCREMENTED.
- * TTIBITS - UPDATED.
- *
- * CALLS DEALLOC.
- #
- ITEM TMP1;
- TRCSTR("PURGETTI$");
- TMP1=CURUSTTIBUF;
- WHYLE TMP1 NQ 0 DO
- BEGIN
- CURUSTTIBUF=0;
- DEALLOC(TTIBITS,TMP1,NUMTTIBIT);
- REMAINTTI=REMAINTTI+1;
- TMP1=TTIBUFLNK[TMP1];
- END
- END # OF PURGETTI #
- PAGE # MAJOR SYSTEM STATE ROUTINES #
- PROC DROPSLICE;
- BEGIN
- #
- ** DROPSLICE - RECALL CPU FOR A LITTLE WHILE.
- *
- * ENTRY NO CONDITIONS.
- *
- * EXIT REAL TIME HAS BEEN DELAYED.
- *
- * CALLS RECALL, INSTRMNT1.
- #
- RECALL(0);
- CONTROL IFEQ METERING,1;
- INSTRMNT1(INSTST"CLOCKTICK");
- CONTROL FI;
- END # OF DROPSLICE #
- PROC DOTIMER;
- BEGIN
- #
- ** DOTIMER - SUPERVISE TIME DEPENDENCIES.
- *
- * DOTIMER IS INTENDED TO BE CALLED ONCE PER MAIN LOOP. THE
- * CPU IS RECALLED ONCE TO ACHIEVE A SMALL DELAY IN REAL TIME,
- * ABOUT 24 MILLISECONDS IF THE INSTALLATION RUNS WITH DEFAULT
- * OPERATOR PARAMETERS, THE TIME OF DAY IS NOTED, AND CERTAIN
- * FUNCTIONS ARE PERFORMED IF THE TIME OF DAY HAS ADVANCED
- * SUFFICIENTLY SINCE THE LAST TIME SUCH FUNCTIONS WERE
- * PERFORMED.
- *
- * ON A CYCLE OF APPROX FIVE TIMES PER SECOND, WE LOOK FOR
- * OPERATOR COMMANDS AND SIGNAL RESTART OF ANY TASKS WHICH ARE
- * DELAYING FOR THE PURPOSE OF ACHIEVING A QUICK RECYCLE OF
- * THE SAME TASK FOR THE SAME USER.
- *
- * ON A CYCLE OF APPROX TWO SECONDS, THE B-DISPLAY MESSAGE IS
- * UPDATED TO SHOW CURRENT LOAD PARAMETERS - NUMBER OF USERS
- * IN THE SUBSYSTEM AND NUMBER OF TASKS CURRENTLY ASSIGNED TO
- * EXECUTE.
- *
- * ENTRY TIMEOFDAY - TIME AT WHICH PREVIOUS CPU SLICE STARTED.
- * NEWTIMEDAY - EQUALS TIMEOFDAY OR TIME AT WHICH A TASK
- * WAS CONSIDERED FOR PREEMPTIVE SWAP, WHICHEVER LARGER.
- * SLICECOUNT - NUMBER OF CYCLES EXECUTED SO FAR.
- * LOGGEDIN - NUMBER OF USERS.
- * TASKSBUSY - NUMBER OF TASKS UTILIZED.
- * ENABLEFLAG - ENABLE/DISABLE NEW USERS OR NO-OP.
- *
- * EXIT OLDTIMEDAY - PREVIOUS VALUE FOR TIMEOFDAY.
- * TIMEOFDAY, NEWTIMEDAY - CURRENT TIME.
- * SLICECOUNT - INCREMENTED.
- * SHUTDOWN, SENSE SWITCHES - REFER TO DOOPER ROUTINE.
- * TASKPULSE[ALL] - 1 IF 5-HERTZ CYCLE OCCURRED.
- * B-DISPLAY UPDATED IF 2-SECOND CYCLE.
- *
- * CALLS DROPSLICE, DOOPER, RTIME, SMFSSTF, SFMCSTF,
- * CHECKTIME(INTERNAL), MESSAGE.
- #
- # HANDLES TIME-OF-DAY DEPENDENT STUFF #
- ITEM LAST5HZ=0, LAST2SEC=0;
- ITEM TMP1, TMP2, BOOL B;
- PROC CHECKTIME(LAST,INTERVAL,FLAG);
- BEGIN
- ITEM LAST, INTERVAL, FLAG B;
- FLAG=FALSE;
- IF TIMEOFDAY-LAST GQ INTERVAL THEN
- BEGIN
- LAST=TIMEOFDAY;
- FLAG=TRUE;
- END
- END # OF CHECKTIME #
- # DOTIMER MAIN CODE STARTS HERE #
- DROPSLICE; # RECALL FOR A WHILE #
- OLDTIMEDAY=NEWTIMEDAY;
- RTIME(TIMEOFDAY);
- B<0,30>TIMEOFDAY=0; # DONT NEED UPPER PART #
- NEWTIMEDAY=TIMEOFDAY;
- SLICECOUNT=SLICECOUNT+1;
- IF ENABLEFLAG NQ 0 THEN
- BEGIN
- IF ENABLEFLAG GQ 0 AND SHUTDOWN EQ 0 THEN SFMSSTF;
- IF ENABLEFLAG LS 0 THEN SFMCSTF;
- ENABLEFLAG=0;
- END
- CHECKTIME(LAST5HZ,200,BOOL); # 5 TIMES PER SECOND #
- IF BOOL THEN
- BEGIN
- DOOPER; # LOOK FOR OPERATOR COMMANDS #
- # ACTIVATE ANY TASKS THAT ARE SPINNING WHEELS #
- FOR CURTASK=1 STEP 1 UNTIL NUMTASKS DO TASKPULSE[CURTASK]=3;
- END
- CHECKTIME(LAST2SEC,2000,BOOL); # ONCE EVERY TWO SECONDS #
- IF BOOL THEN
- BEGIN
- # DISPLAY LOAD FACTORS #
- TMP1=LOGGEDIN;
- FOR TMP2=3 STEP -1 UNTIL 0 DO
- BEGIN
- C<TMP2,1>STATUSMSG=MOD(TMP1,10)+O"33";
- TMP1=TMP1/10;
- END
- C<12,1>STATUSMSG=O"33"+MOD(TASKSBUSY,10);
- C<11,1>STATUSMSG=O"33"+MOD(TASKSBUSY/10,10);
- C<28,2>STATUSMSG=0;
- MESSAGE(STATUSMSG,1,1);
- END
- END # OF DOTIMER #
- PROC DOOPER;
- BEGIN
- #
- ** DOOPER - PERFORM OPERATOR FUNCTIONS.
- *
- * DOOPER SHOULD BE CALLED FROM TIME TO TIME TO SEE IF THE
- * ENVIRONMENT INDICATES AN OPERATIONAL CHANGE IS OCCURRING.
- *
- * THE FIRST ISSUANCE OF "IDLE,SMF." INDICATES THAT SMFEX
- * SHOULD ENROLL NO NEW USERS AND SHOULD TRANSITION EXISTING
- * USERS BACK TO THEIR SINGLE-USER EDITORS WITH COMPLETE
- * TRANSPARENCY. THIS CAN BE DONE AS THE USERS CYCLE THROUGH
- * THE MAIN LOOP OF THE EDITOR. WHEN THE USER COUNT REACHES
- * ZERO, SMFEX WILL SHUT DOWN.
- *
- * A SECOND ISSUE OF THE IDLE COMMAND REQUESTS THAT SMFEX GET
- * OUT OF THE SYSTEM MORE RAPIDLY, POSSIBLY AT THE EXPENSE OF
- * SOME USERS RECEIVING INTERRUPT WARNING MESSAGES BUT STILL
- * WITH NO LOSS OF DATA. SMFEX CAN STOP AS QUICKLY AS IT CAN
- * GET ANY CURRENT TASKS TO LEAVE THEIR INTERNAL CONTROL POINTS.
- *
- * A THIRD ISSUE OF THE IDLE COMMAND REQUESTS EVEN MORE RAPID
- * SHUTDOWN. ANY CURRENT TASKS WILL BE PAUSED AT THEIR NEXT
- * CIO RECALL. THUS SOME USER COMMANDS MAY NOT COMPLETE, BUT
- * NO EDIT SESSIONS WILL SUFFER REGRESSIVE DAMAGE.
- *
- * ANY TIME DOOPER DETECTS EITHER THE SLOWDOWN MODE OR THE
- * QUICK IDLE MODE, IT SETS THE ENABLEFLAG SO THAT DOTIMER
- * WILL DISABLE THE ACCESSABILITY OF THE SUBSYSTEM.
- *
- * ENTRY SHUTDOWN - PREVIOUS SHUTDOWN LEVEL IF ANY.
- * 0 = NORMAL PROCESSING.
- * 1 = ACCEPT NO USERS, KEEP RUNNING.
- * 2 = SPECIAL FOR RECOVERY FUNCTION.
- * 3 = SHUTDOWN WHEN TASKS BECOME EMPTY.
- * 4 = SHUTDOWN WHEN CIO CALLS COMPLETE.
- * SWAPGOOD, SWAPBAD - EXTENDED MEMORY CONTROLS.
- *
- * EXIT SHUTDOWN - UPDATED.
- * MEM[0] - UPDATED TO ACKNOWLEDGE IDLE COMMAND.
- * ENABLEFLAG - FORCED NEGATIVE IF DETECT NEW NON-TRIVIAL
- * VALUE FOR SHUTDOWN FLAG.
- #
- ITEM TMP1;
- IF SHUTDOWN EQ 2 THEN RETURN;
- IF MEM[0] LAN O"100000" NQ 0 THEN # IDLE,SMF. #
- BEGIN
- IF IDLEDOWN THEN STOPNOW=TRUE;
- ELSE IF ACCEPTNONE THEN IDLEDOWN=TRUE;
- ELSE ACCEPTNONE=TRUE;
- MEM[0]=MEM[0] LXR O"100000"; # ACKNOWLEDGE IDLE COMMAND #
- ONSW(O"40"); # SIGNAL SUBSYSTEM TERMINATION #
- END
- TMP1=0;
- IF ACCEPTNONE THEN TMP1=1;
- IF IDLEDOWN THEN TMP1=3;
- IF STOPNOW THEN TMP1=4;
- IF SHUTDOWN NQ TMP1 THEN
- BEGIN
- IF TMP1 NQ 0 THEN ENABLEFLAG=-1;
- ELSE ENABLEFLAG=1;
- END
- SHUTDOWN=TMP1;
- CONTROL IFEQ ECSCODE,1;
- IF ECSDOWN THEN P<SWAPMASK>=LOC(SWAPBAD);
- ELSE P<SWAPMASK>=LOC(SWAPGOOD);
- CONTROL FI;
- END # OF DOOPER #
- PAGE # DOINPUT -- RECEIVE SIC MSG AND QUEUE #
- PROC DOINPUT;
- BEGIN
- #
- ** DOINPUT - ACCEPT MESSAGES FROM IAFEX.
- *
- * DOINPUT SUPERVISES ALL MESSAGE RECEIVED FROM IAF, AND
- * SHOULD BE CALLED BY THE MAIN LOOP ONCE PER RECALL CYCLE.
- * IAF COMMUNICATES WITH SMF BY USING THE SCP/UCP FACILITY
- * (IAF IS THE SCP AND SMF IS THE UCP) TO PLACE MESSAGES
- * INSIDE THE SMF FIELD LENGTH. THE ADDRESS OF THE SMF WINDOW
- * FOR MESSAGES WAS ESTABLISHED BY SMF WHEN IT FIRST SENT A
- * MESSAGE TO IAF. IAF CANNOT SEND ITS NEXT MESSAGE UNTIL SMF
- * ACKNOWLEDGES THE CURRENT MESSAGE BY CLEARING THE HEADER
- * WORD.
- *
- * NOTE THAT THE DOINPUT ROUTINE PROCESSES RECEIPT OF
- * MESSAGES, BUT HAS NOTHING TO DO WITH SENDING MESSAGES TO
- * IAFEX. THAT FUNCTION IS PROVIDED AS TASKS EXECUTE VIA
- * EXECUTIVE ROUTINES CALLED BY THE EDITOR MODULE. DOINPUT
- * CAN TRANSMIT A MESSAGE TO IAFEX, BUT ONLY UNDER THE
- * EMERGENCY SITUATION WHERE THE USER TABLE HAS OVERFLOWED, IN
- * WHICH CASE THE USER BEING CONNECTED MUST BE IMMEDIATELY
- * DISCONNECTED BEFORE ANY OTHER SMFEX PROCESSING CAN PROCEED.
- * THIS SITUATION IS NORMALLY DISCOURAGED BY LOGIC TO DISABLE
- * SMFEX SUBSYSTEM ACCESSABILITY WHEN THE USER TABLE GETS
- * CLOSE TO THE FULL CONDITION.
- *
- * MESSAGES FROM IAF ARE OF TWO BASIC FORMS - FIRST, A
- * QUICK-SHUTDOWN IS INDICATED BY NON-ZERO CONTENT APPEARING
- * IN SSCINP[-1], AND SECOND, A PRODUCTION MESSAGE IS
- * INDICATED BY NON-ZERO CONTENT IN ONE OR MORE WORDS STARTING
- * WITH SSCINP[0].
- *
- * PRODUCTION MESSAGES CAN APPEAR IN SIX VARIATIONS - (1)
- * INITIALIZATION OF IAF, (2) COMMAND TEXT, (3)
- * ACKNOWLEDGEMENT THAT OUTPUT HAS BEEN RECEIVED AND MORE CAN
- * BE ACCEPTED, (4) USER BREAK, (5) DETACHMENT OF TERMINAL
- * FROM JOB, AND (6) CONNECTION OF A NEW USER INTO SMFEX.
- *
- * THE SECOND THRU FIFTH MESSAGE TYPES REQUIRE REFERENCE TO AN
- * EXISTING USER WITHIN SMFEX. THE SECOND MESSAGE TYPE
- * CARRIES ARBITRARY TEXT ALONG WITH THE HEADER WORD, AND THE
- * SIXTH MESSAGE TYPE CARRIES ONE WORD OF TEXT WITH THE HEADER
- * WORD. THE OTHER MESSAGE TYPES CONSIST SOLELY OF THE HEADER
- * WORD.
- *
- * COMMAND MESSAGES CAUSE SCHEDULING OF THE USER FOR TASK
- * PROCESSING, AND TO ENABLE THE RECEIPT OF ADDITIONAL
- * MESSAGES FROM IAF WHILE THE TASK SWAPS IN, THE MESSAGE TEXT
- * IS QUEUED IN ONE OF THE TERMINAL INPUT BUFFERS. SINCE ONE
- * COMMAND MESSAGE MAY BE JUST A FRAGMENT OF THE ENTIRE
- * COMMAND TEXT, INPUT BUFFERS ARE LINKED TO THE USER AND TO
- * EACH OTHER AS NEEDED.
- *
- * SMFEX ATTEMPTS TO AVOID RUNNING OUT OF INPUT BUFFERS WITH
- * "TRY HARDER" TASK SCHEDULING RULES, BUT IF BUFFERS DO GET
- * EXHAUSTED, THEN DOINPUT SIMPLY NEGLECTS TO CLEAR AWAY THE
- * IAF WINDOW AT SSCINP[0], THUS PREVENTING IAF FROM SENDING
- * MORE MESSAGES UNTIL WE CATCH UP AND CAUSING FUTURE DOINPUT
- * CYCLES TO ONCE AGAIN ATTEMPT TO QUEUE THE INPUT. IN THE
- * EXTREME CASE WHERE SMFEX FALLS BEHIND WITH IAFEX HOLDING 64
- * MESSAGES IN ITS OWN QUEUE, THEN IAFEX WILL TREAT SMFEX AS A
- * DERELICT AND REVERT ALL USERS BACK TO SINGLE-USER MODE.
- *
- * USER BREAKS AND DETACHMENTS CAUSE TASK SCHEDULING WITH
- * APPROPRIATE FLAGS SET SO THE TASK WILL INTERRUPT NORMAL
- * PROCESSING AND REACT ACCORDINGLY. FOR DETACHMENT, IAF
- * DELAYS DETACH COMPLETION UNTIL SMFEX FINALLY TRANSMITS AN
- * END-OF-EDIT MESSAGE.
- *
- * OUTPUT ACCEPTANCE MESSAGES CAUSE TASK SCHEDULING FOR
- * CONTINUED EXECUTION.
- *
- * CONNECTION MESSAGES CAUSE SMFEX TO ALLOCATE A NEW TABLE
- * ENTRY FOR THE USER, SAVING THE JSN AND EJT ORDINAL PROVIDED
- * IN THE SECOND WORD OF THE MESSAGE, WITH THE NEW USER
- * SCHEDULED FOR TASK EXECUTION SO THAT THE TRANSFERRED
- * WORKFILE CAN BE QUICKLY VALIDATED.
- *
- * ENTRY SSCINP[-1] - AS CLEARED BY PREVIOUS DOINPUT, OR
- * NEW SHUTDOWN MESSAGE FROM IAFEX.
- * SSCINP[0] - AS CLEARED BY PREVIOUS DOINPUT, OR
- * HEADER OF NEW MESSAGE FROM IAFEX.
- * SHUTDOWN - WHETHER TO PROCESS INPUT NORMALLY.
- * USER AND TASK TABLES SETUP.
- * REMAINTTI - NUMBER OF INPUT QUEUE BUFFERS LEFT.
- * TTIBITS - ALLOCATION BITMASK FOR INPUT BUFFERS.
- * TTIBUFADDR[ALL] - WHERE THE INPUT BUFFERS ARE.
- * TTIBUFLNK[ALL] - EXISTING LINKAGES OF GROUPED BUFFERS.
- * LOGGEDIN - NUMBER OF USERS IN SMFEX.
- * MAXLOGGED - HIGH WATER MARK OF LOGGEDIN.
- * SWAP QUEUE - SETUP.
- *
- * EXIT SSCINP[-1] - CLEARED.
- * SSCINP[0] - CLEARED UNLESS REMAINTTI WAS ZERO WITH
- * A COMMAND MESSAGE AWAITING QUEUING.
- * LOGGEDIN - INCREMENTED IF CONNECTION MESSAGE.
- * MAXLOGGED - HIGH WATER MARK.
- * REMAINTTI - DECREMENTED IF COMMAND MESSAGE ARRIVED
- * AND REMAINTTI WAS NOT ALREADY ZERO.
- * SWAP QUEUE - UPDATED AS NEEDED.
- * TERMINAL INPUT BUFFERS - IF ALLOCATED, THEN LINKED TO
- * USER TABLE ENTRY OR TO EXISTING BUFFERS.
- * USER TABLE ENTRY - UPDATED AS NEEDED.
- * MEM[0] - SENSE SWITCH 6 SET AS NEEDED.
- * ENABLEFLAG - FORCED NEGATIVE IF NEARING FULL TABLE.
- *
- * CALLS MELT, INSTRMNT2, INSTRMNT1, ALLOC, MOVEWD,
- * SCHEDULE, PURGETTI, SYSTEM, RECALL, GETUSER, PUTINQ,
- * PUTUSER, MAX.
- *
- * USES IAFHEADER, CURUSER.
- #
- ITEM TMP1,TMP2,TMP3;
- SWITCH RCVFNCSW RCVINIT,RCVMSGIN,RCVOUTDONE,RCVBREAK,
- RCVHUNGUP,RCVCONNECT;
- ARRAY VALIDATE[0:5]; ITEM VLDTUSR B=[FALSE,4(TRUE),FALSE];
- ARRAY REJECTION [0:1]; ITEM REJECTMSG;
- ITEM EJT;
- IF SSCINP[-1] NQ 0 THEN
- BEGIN
- STOPNOW=TRUE;
- SSCINP[-1]=0;
- ONSW(O"40"); # SIGNAL SUBSYSTEM TERMINATION #
- END
- IF SHUTDOWN GR 1 THEN RETURN;
- IAFHEADER=SSCINP[0];
- IF IAFHEADER NQ 0 THEN # WE HAVE RECEIVED SOMETHING #
- BEGIN
- IF VLDTUSR[IAFFUNC] THEN
- BEGIN
- CURUSER=0;
- # SEARCH FOR USER AMONG RECENT TASK ASSIGNMENTS #
- FOR TMP1=1 STEP 1 UNTIL TASKSAVAIL DO
- BEGIN
- IF TASKUSER[TMP1] NQ 0 AND USERIAFNUM[TASKUSER[TMP1]]
- EQ IAFTERM THEN
- BEGIN
- CURUSER=TASKUSER[TMP1];
- GOTO RCVFOUND;
- END
- END
- # SEARCH FOR USER BY BRUTE FORCE #
- FOR TMP1=1 STEP 1 UNTIL NUMSMFUSR DO
- BEGIN
- IF USERIAFNUM[TMP1] EQ IAFTERM THEN
- BEGIN
- CURUSER=TMP1;
- GOTO RCVFOUND;
- END
- END
- RCVFOUND:
- IF CURUSER LQ 0 OR CURUSER GR NUMSMFUSR THEN
- BEGIN
- SSCINP[0]=0;
- GOTO AFTERRCV;
- END
- GETUSER;
- END
- GOTO RCVFNCSW[IAFFUNC];
- RCVMSGIN:
- CONTROL IFEQ TRACEFLAG,1;
- P<MOVFROM>=LOC(SSCINP[1]);
- TMP1=IAFLEN-1;
- CONTROL FI;
- TRCBOTH("MSGIN$",CURUSER);
- TRCWORDS(MOVFROM,TMP1);
- CONTROL IFGQ PARANOIA,2;
- IF NOT CURUSLOGGED THEN MELT("DOIN 2$");
- IF IAFLEN GR SIZTTIBUF+1 THEN MELT("DOIN 22$");
- CONTROL FI;
- IF IAFLEN LS 2 THEN
- BEGIN
- SSCINP[0]=0;
- GOTO AFTERRCV;
- END
- CONTROL IFEQ METERING,1;
- INSTRMNT2(INSTST"INPUT",IAFLEN);
- CONTROL FI;
- IF REMAINTTI LQ 0 THEN # TRY ANOTHER DAY #
- BEGIN
- CONTROL IFEQ METERING,1;
- INSTRMNT1(INSTST"NOTTI");
- CONTROL FI;
- GOTO PASTRCV;
- END
- ALLOC(TTIBITS,TTIGOOD,TMP2,NUMTTIBIT);
- CONTROL IFGQ PARANOIA,2;
- IF TMP2 EQ 0 THEN MELT("DOIN 4$"); # MUST SUCCEED #
- CONTROL FI;
- REMAINTTI=REMAINTTI-1; # KEEP TRACK RESOURCE #
- P<MOVFROM>=LOC(SSCINP[1]);
- P<MOVTO>=TTIBUFADDR[TMP2];
- TMP3=IAFLEN-1;
- MOVEWD(TMP3,MOVFROM,MOVTO);
- TTIBUFLEN[TMP2]=TMP3;
- TTIBUFLNK[TMP2]=0;
- IF CURUSTTIBUF EQ 0 THEN # START NEW CHAIN #
- BEGIN
- CURUSTTIBUF=TMP2;
- CONTROL IFEQ METERING,1;
- TMP1=TIMEOFDAY-CURUSLASTIM;
- INSTRMNT2(INSTST"THNK",TMP1);
- CONTROL FI;
- END
- ELSE # ADD TO CHAIN #
- BEGIN
- TMP1=CURUSTTIBUF;
- WHYLE TMP1 NQ 0 DO
- BEGIN
- TMP3=TMP1;
- TMP1=TTIBUFLNK[TMP1];
- END
- TTIBUFLNK[TMP3]=TMP2;
- END
- SCHEDULE;
- GOTO ENDRCV;
- RCVBREAK:
- TRCBOTH("BREAK$",CURUSER);
- CONTROL IFEQ METERING,1;
- INSTRMNT1(INSTST"BREAKS");
- CONTROL FI;
- IF NOT CURUSLOGGED THEN GOTO ENDRCV;
- CURUSINTRPT=TRUE;
- CURUSCRUNCH=FALSE; # IMPROVE SCHEDULEING PRIORITY #
- PURGETTI;
- SCHEDULE;
- GOTO ENDRCV;
- RCVHUNGUP:
- TRCBOTH("HUNGUP$",CURUSER);
- CONTROL IFEQ METERING,1;
- INSTRMNT1(INSTST"HANGUPS");
- CONTROL FI;
- CURUSDROP=TRUE;
- CURUSRCVRY=TRUE;
- GOTO RCVBREAK;
- RCVINIT:
- STOPNOW=TRUE;
- GOTO AFTERRCV;
- RCVOUTDONE: # TTY OUTPUT COMPLETE #
- TRCBOTH("TOCIN $",CURUSER);
- CONTROL IFGQ PARANOIA,3;
- IF NOT CURUSLOGGED THEN MELT("DOIN 43$");
- CONTROL FI;
- SCHEDULE;
- GOTO ENDRCV;
- RCVCONNECT:
- TRCBOTH("CONNECT$",IAFTERM);
- IF IAFTERM GR MAXCONNECT THEN MELT("TABLE LIMIT$");
- CURUSER=0;
- FOR TMP1=1 STEP 1 UNTIL NUMSMFUSR DO
- BEGIN
- IF USERIAFNUM[TMP1] EQ IAFTERM THEN CURUSER=TMP1;
- IF CURUSER EQ 0 THEN
- BEGIN
- IF NOT USERLOGGED[TMP1] THEN CURUSER=TMP1;
- END
- END
- TRCBOTH("PICK USER$",CURUSER);
- IF CURUSER EQ 0 THEN
- BEGIN
- # CRITICAL TABLE SPACE SHORTAGE - SEND LOGOUT FUNCTION TO #
- # IAF IMMEDIATELY AND SERIALIZE UNTIL THIS IS ACCOMPLISHED #
- EJT=B<48,12>SSCINP[1];
- TRYREJECT:
- IAFFUNC=SMF2IAF"LOGOUT";
- IAFLEN=1;
- IAFPTR=0;
- REJECTMSG[0]=0;
- REJECTMSG[1]=IAFHEADER;
- P<SSCBUFFER>=LOC(REJECTION);
- SSCTYPE=O"3";
- SSCCOUNT=1;
- SYSREQ("SSC",0,LOC(SSCBUFFER),IAFSSID);
- IF SSCSTATUS LAN O"7776" EQ 4 THEN
- BEGIN
- RECALL(0);
- GOTO TRYREJECT;
- END
- EESET((TTEQ*4096)+EJT);
- GOTO AFTERRCV;
- END
- USERFLAGS[CURUSER]=0;
- GETUSER;
- CURUSLOGGED=TRUE;
- CURUSSTART=TRUE;
- CURUSIAFNUM=IAFTERM;
- USERJSN[CURUSER]=C<0,4>SSCINP[1];
- USEREJT[CURUSER]=B<48,12>SSCINP[1];
- LOGGEDIN=LOGGEDIN+1;
- IF LOGGEDIN GQ NUMSMFUSR-2 THEN ENABLEFLAG=-1;
- CONTROL IFEQ METERING,1;
- MAXLOGGED=MAX(MAXLOGGED,LOGGEDIN);
- CONTROL FI;
- PUTINQ;
- GOTO ENDRCV;
- ENDRCV:
- CURUSLASTIM=TIMEOFDAY;
- SSCINP[0]=0;
- PASTRCV:
- PUTUSER;
- AFTERRCV:
- END # OF BUFFER0 HANDLER #
- END # OF DOINPUT #
- PAGE # RUNJOBS -- TRY TO DO SOME USER CODE #
- PROC RUNJOBS;
- BEGIN
- #
- ** RUNJOBS - SUPERVISE TASK EXECUTION.
- *
- * RUNJOBS CONTROLS TASK EXECUTION. TASKS GET THE CPU ONLY
- * FROM RUNJOBS, AND ARE REQUIRED TO EXIT EACH TIME SLICE TO
- * THE APPROPRIATE LABEL WITHIN RUNJOBS. SINCE RUNJOBS IS THE
- * SOLE PATH FOR TASKS TO RECEIVE CONTROL, IT IS NOT NECESSARY
- * FOR RUNJOBS ITSELF TO USE REENTRANT ENTRY AND EXIT EVEN
- * THOUGH ITS SUBROUTINES ARE THEMSELVES REENTRANT.
- *
- * NOTE THAT THERE IS NO ARCHITECTURAL PROTECTION AGAINST
- * RENEGADE TASKS. IF A TASK LOOPS OR OVERWRITES MEMORY, THE
- * ENTIRE SUBSYSTEM WILL BE IMPACTED. THEREFORE, MULTI-USER
- * EDITING CODE MUST BE BUG-FREE. EDITING CODE MUST ALSO BE
- * SENSITIVE AND REASONABLE IN RESOURCE CONSUMPTION SINCE THIS
- * SUBSYSTEM EXECUTES AT A VERY HIGH PRIORITY.
- *
- * RUNJOBS PERFORMS TWO PRELIMINARY PHASES BEFORE INITIATING
- * TASKS. THE FIRST PRELIMINARY PHASE ACCOUNTS FOR THE LEVEL
- * OF UTILIZATION, BOTH FOR STATISTICAL REASONS AND TO ENABLE
- * SCHEDULING RULES TO "TRY HARDER". THE SECOND PRELIMINARY
- * PHASE CHECKS FOR SHUTDOWN CONDITIONS.
- *
- * THE PRINCIPAL FUNCTION OF RUNJOBS IS TO ADVANCE THE STATUS
- * OF EACH AVAILABLE TASK. WHILE THE SUBSYSTEM IS COMPILED
- * WITH A LARGE NUMBER OF TASKS IN EXISTENCE, THE NUMBER OF
- * TASKS AVAILABLE FOR EXECUTION IS DETERMINED AT SUBSYSTEM
- * STARTUP AND IS TYPICALLY MUCH SMALLER.
- *
- * EACH TASK CAN HAVE ANY OF THE FOLLOWING STATUSES --
- *
- * 1. IT MAY BE EMPTY. AN EMPTY TASK WILL BE ASSIGNED TO A
- * USER IF THERE ARE USERS IN THE SCHEDULING (SWAPIN) QUEUE
- * AND NO SHUTDOWN CONDITION EXISTS. IN ASSIGNING A USER TO A
- * PREVIOUSLY EMPTY TASK, THE TASK STATUS IS CHANGED TO
- * "START" OR "SWAPIN" BASED ON THE USER'S PROGRESS.
- *
- * 2. IT MAY BE DELAYING. A DELAYING TASK MISSES THE CPU FOR
- * PRECISELY ONE SMFEX CPU RECALL CYCLE, AND TYPICALLY IS
- * WASTING REAL TIME WHILE POLLING ON COMPLETION OF AN I/O
- * FUNCTION. IN VIEW OF THE BRUTE FORCE REQUIRED TO RESTART A
- * DELAYED TASK, THIS STYLE OF WAITING FOR I/O IS NOT USED
- * OFTEN WITHIN THE EDITING CODE, BUT IT IS FULLY SUPPORTED BY
- * THIS EXECUTIVE. RUNJOBS RESTARTS A DELAYED TASK AS SOON AS
- * IT IS DISCOVERED, BY CHANGING THE TASK STATUS TO "RUN".
- *
- * 3. A TASK MAY BE IN AUTO RECALL. THIS TASK WISHES TO MISS
- * THE CPU UNTIL SMFEX DETECTS THAT THE SPECIFIED COMPLETION
- * BIT HAS BEEN TOGGLED BY ANYBODY. THIS IS THE METHOD
- * GENERALLY USED WITHIN THE EDITOR TO WAIT FOR I/O, SINCE IT
- * AVOIDS WASTING CPU TIME TO START UP A DELAYED TASK WHICH IS
- * LIKELY TO DROP RIGHT BACK INTO DELAY. ONCE SMFEX VERIFIES
- * THAT THE DESIRED EVENT IS COMPLETE, IT RESTARTS A RECALLED
- * TASK BY CHANGING THE TASK STATUS TO "RUN".
- *
- * 4. A TASK MAY BE IN "START" STATUS. THIS TASK IS READY
- * FOR THE CPU, FOR A USER WHO HAS NOT YET EXECUTED ANY
- * MULTI-USER EDITING CODE. THE TASK WILL GET THE CPU AT THE
- * EDITOR'S MAIN ENTRY POINT. NO SWAP PAGE EXISTS YET, AND
- * DISPATCHING DATA IS IN MODEL FORMAT.
- *
- * 5. A TASK MAY BE IN "SWAPIN" STATUS. THIS TASK HAS
- * PREVIOUSLY EXECUTED AND SWAPPED OUT. THE TASK THEREFORE
- * WANTS THE CPU AT THE ENTRY POINT OF THE SWAPPING CODE.
- * SINCE THE SWAPOUT AND SWAPIN CODE ARE ONE AND THE SAME,
- * TASK CPU DISPATCHING IS EFFECTED BY RETURNING TO THE SWAP
- * CODE WHERE CONTROL WAS PREVIOUSLY SURRENDERED. THAT SWAP
- * CODE WILL READ IN THE SWAP CODE AND ALTER THE MEMORY IMAGE
- * FOR THE TASK ON THE FLY, THEN RETURN OUT THE THE EDITING
- * CODE WHICH HAD CAUSED THE PREVIOUS SWAPOUT.
- *
- * 6. A TASK MAY BE IN "RUN" STATUS. THIS TASK HAS BEEN
- * SWAPPED IN FOR SOME TIME, AND IS PRESENTLY COMPLETING A
- * DELAY OR RECALL. SINCE THE MEMORY IMAGE FOR THE TASK IS
- * INTACT, WE ARE REQUIRED ONLY TO MANIPULATE THOSE ARRAYS
- * CRITICAL TO TASK DISPATCHING, AND RETURN TO THE POINT IN
- * THE EDITING CODE WHERE THE TASK HAD PREVIOUSLY PAUSED.
- *
- * EACH TIME A TASK GETS THE CPU, IT CAN FINISH ITS TIME SLICE
- * IT THREE WAYS -- (1) THE ENTIRE EDIT SESSION MAY END, IN
- * WHICH CASE THE TASK EXITS VIA LABEL "AFTEREDIT" FOR CLEANUP
- * PROCESSING, OR (2) THE TASK MAY COMPLETE A TRANSACTION,
- * I.E., IT MAY FINISH SWAPPING OUT FOR TERMINAL I/O OR
- * RESOURCE BALANCING, IN WHICH CASE IT EXITS VIA LABEL
- * "AFTERTRANS", OR (3) IT MAY NEED TO DELAY/RECALL WITHIN ITS
- * MEMORY IMAGE (I.E., WHILE STILL SWAPPED IN) FOR SOME DISK
- * I/O OR OTHER SHORT-TERM EVENT, IN WHICH CASE IT EXITS VIA
- * LABEL "AFTERSLICE".
- *
- * IN SUMMARY, THERE ARE THREE WAYS FOR A TASK TO BE ASSIGNED
- * THE CPU (START OF SESSION, START OF TRANSACTION, OR RESTART
- * AFTER DELAY) AND THREE WAYS FOR A TASK TO FORFEIT THE CPU
- * (END OF SESSION, END OF TRANSACTION, DELAY), AND THESE
- * ENTRIES AND EXITS CAN BE MIXED IN ANY FASHION. AS A
- * RESULT, RUNJOBS MUST VIOLATE A RULE OF CLEAN PROGRAMMING
- * PRACTISE, IN ALLOWING JUMPS INTO BLOCKS OF CODE (IF-THEN,
- * NOT LOOPS) WHICH ARE NOT NECESSARILY ACTIVE.
- *
- *
- * ENTRY SHUTDOWN - CONTROLS WHETHER TO EXECUTE AT ALL.
- * SWPQHEAD - START OF SWAPIN QUEUE.
- * TASKSAVAIL - NUMBER OF TASKS WE CAN USE.
- * TASK AND USER TABLES - SETUP.
- * MODELPTR, MODELLEN - MODEL FORMAT DISPATCH DATA.
- * TIMEOFDAY - MILLISECOND CLOCK.
- * LOGGEDIN - NUMBER OF USERS.
- *
- * EXIT TASKSBUSY - NUMBER OF NON-EMPTY TASKS.
- * COMPLETE - FORCED TRUE BASED ON SHUTDOWN.
- * LOGGEDIN - DECREMENTED FOR ANY SESSION COMPLETIONS.
- * ENABLEFLAG - NON-ZERO POSITIVE IF LOGGEDIN
- * DECREMENTS OUT OF NEAR-FULL CONDITION.
- * USER AND TASK TABLES - UPDATED AS NEEDED.
- *
- * CALLS INSTRMNT1, GETUSER, TAKEOFFQ, PUTUSER, GETCOMMON,
- * MOVEWD, GENWRKNAM, EDTINIT, PROCESS, EDTTERM,
- * MELT, ABTKILL, ABTPAUSE, RTRNWRKFIL, SENDLOGOUT,
- * KILL, TRANSACT, PUTINQ, SPREAD, GATHER.
- *
- * USES CURUSER, CURTASK, RSTKPTR, RENTSTK.
- *
- * NOTE WHENEVER RUNJOBS INVOKES A TASK, BY CALLING
- * PROCESS, TRANSACT, OR RESUME, THE FOLLOWING
- * CONVENTIONS APPLY FOR PARAMETERS PASSED TO AND
- * FROM THE EDITOR CODE --
- *
- * PASSED CURTASK, CURUSER, RSTKPTR, RENTSTK,
- * WORKNAM, P<MANY ARRAYS>.
- *
- * RETURNED ABORTED, RSTKPTR, RENTSTK,
- * CHNGSTATUS, TASKRCLADR[CURTASK].
- #
- ITEM TMP1,TMP2;
- XDEF LABEL AFTEREDIT;
- XDEF LABEL AFTERTRANS;
- XDEF LABEL AFTERSLICE;
- XREF LABEL RESUME;
- TASKSBUSY=0; # COUNT UP TASK UTILIZATION #
- FOR TMP1=1 STEP 1 UNTIL NUMTASKS DO IF TASKSTATUS[TMP1] NQ
- TASKST"EMPTY" THEN TASKSBUSY=TASKSBUSY+1;
- CONTROL IFEQ METERING,1;
- IF TASKSBUSY GQ TASKSAVAIL AND SWPQHEAD NQ 0
- THEN INSTRMNT1(INSTST"NOTASK");
- CONTROL FI;
- IF SHUTDOWN GR 1 THEN # SEE IF SINUSES CLEARED #
- BEGIN
- IF TASKSBUSY EQ 0 THEN # ALL ACTIVITY CEASED #
- BEGIN
- IF (SHUTDOWN GQ 2 AND SWPQHEAD EQ 0) OR
- SHUTDOWN EQ 4 THEN COMPLETE=TRUE;
- END
- END
- IF SHUTDOWN EQ 1 AND LOGGEDIN EQ 0 THEN COMPLETE=TRUE;
- FOR CURTASK=1 STEP 1 UNTIL TASKSAVAIL DO
- BEGIN
- IF SWPQHEAD NQ 0 AND SHUTDOWN LQ 3
- AND TASKSTATUS[CURTASK] EQ TASKST"EMPTY" THEN
- BEGIN
- CURUSER=SWPQHEAD;
- WHYLE CURUSER NQ 0 AND USERTTIBUF[CURUSER] EQ 0
- DO CURUSER=USERQUELNK[CURUSER];
- IF CURUSER EQ 0 THEN
- BEGIN
- CURUSER=SWPQHEAD;
- WHYLE CURUSER NQ 0 AND USERCRUNCH[CURUSER]
- DO CURUSER=USERQUELNK[CURUSER];
- IF CURUSER EQ 0 THEN CURUSER=SWPQHEAD;
- END
- TRCBOTH("ASGN SLT$",CURTASK); TRCDEC(CURUSER);
- GETUSER;
- CURUSCRUNCH=FALSE;
- CURUSINTASK=TRUE;
- CURUSTASK=CURTASK;
- TAKEOFFQ;
- TASKUSER[CURTASK]=CURUSER;
- TASKFLAGS[CURTASK]=0; # CLEAR ALL #
- TASKNXTTTO[CURTASK]=0;
- TASKTYPTTO[CURTASK]=0;
- IF CURUSSTART THEN TASKSTATUS[CURTASK]=TASKST"START";
- ELSE TASKSTATUS[CURTASK]=TASKST"SWAP";
- PUTUSER;
- END
- IF TASKSTATUS[CURTASK] EQ TASKST"EMPTY" THEN TEST CURTASK;
- IF TASKSTATUS[CURTASK] EQ TASKST"DELAY" THEN
- BEGIN
- TASKSTATUS[CURTASK]=TASKST"RUN";
- END
- IF TASKSTATUS[CURTASK] EQ TASKST"RECALLFET" THEN
- BEGIN
- IF B<59,1>MEM[TASKRCLADR[CURTASK]] EQ 1 THEN
- BEGIN
- TASKSTATUS[CURTASK]=TASKST"RUN";
- END
- END
- IF TASKSTATUS[CURTASK] EQ TASKST"START" THEN
- BEGIN
- CURUSER=TASKUSER[CURTASK];
- TRCBOTH("TASK STRT$",CURTASK); TRCDEC(CURUSER);
- GETUSER;
- CONTROL IFEQ METERING,1;
- INSTRMNT1(INSTST"SESSION");
- CONTROL FI;
- CURUSSTART=FALSE;
- RSTKPTR=1; # MAKE A NEW STACK #
- GETCOMMON; # SET ARRAY BASES #
- P<MOVFROM>=MODELPTR;
- MOVEWD(MODELLEN,MOVFROM,DATAEND); # VIRGIN EDIT DATA #
- GENWRKNAM;
- TASKTIME[CURTASK]=TIMEOFDAY; # SINCE NO SWAPIN #
- IF NOT CURUSRCVRY THEN
- BEGIN
- EDTINIT;
- PROCESS;
- EDTTERM;
- END
- AFTEREDIT: # CONTROL FORCE HERE IF RCVRY #
- CONTROL IFEQ METERING,1;
- INSTRMNT1(INSTST"ENDEDT");
- CONTROL FI;
- CURUSDONE=TRUE;
- CONTROL IFEQ TRACEFLAG,1;
- IF ABORTED THEN TRACESTR("ABORTEDIT$");
- ELSE TRACESTR("ENDEDIT$");
- CONTROL FI;
- CONTROL IFEQ MELTONABT,1;
- IF ABORTED THEN MELT("SUBTASK ABORT$");
- CONTROL FI;
- RSTKPTR=1;
- IF ABORTED THEN
- BEGIN
- IF TASKABORT[CURTASK] THEN ABTKILL;
- ELSE
- BEGIN
- TASKABORT[CURTASK]=TRUE;
- ABTPAUSE;
- TASKABORT[CURTASK]=FALSE;
- END
- END
- RTRNWRKFIL; # RETURN THE WORK FILE #
- SENDLOGOUT; # TRANSMIT LOGOUT FUNCTION #
- LOGGEDIN=LOGGEDIN-1;
- IF LOGGEDIN EQ NUMSMFUSR-5 THEN ENABLEFLAG=1;
- TASKSTATUS[CURTASK]=TASKST"EMPTY";
- LASTTASK=0;
- KILL;
- END
- IF TASKSTATUS[CURTASK] EQ TASKST"SWAP" THEN
- BEGIN
- CURUSER=TASKUSER[CURTASK];
- TRCBOTH("TASK TRNS$",CURTASK); TRCDEC(CURUSER);
- GETUSER;
- RSTKPTR=CURUSSTKPTR ; # HE REMEMBERS HIS PLACE #
- GETCOMMON;
- FETFNT=CURUSFNTPTR;
- GENWRKNAM;
- TRANSACT; # RUNS AS SUBROUTINE OF USER #
- AFTERTRANS: # CONTROL COMES HERE MANUALLY FROM TRANSACT/ENDTRANS #
- CURUSSTKPTR=RSTKPTR;
- CURUSFNTPTR=FETFNT;
- CURUSINTASK=FALSE;
- IF TASKREQUE[CURTASK] THEN PUTINQ;
- TASKSTATUS[CURTASK]=TASKST"EMPTY";
- LASTTASK=0;
- PUTUSER;
- END
- IF TASKSTATUS[CURTASK] EQ TASKST"RUN" THEN
- BEGIN
- CURUSER=TASKUSER[CURTASK];
- TRCBOTH("TASK RUN$",CURTASK); TRCDEC(CURUSER);
- GETUSER;
- IF SHUTDOWN EQ 4 THEN # SELF DESTRUCT #
- BEGIN
- TASKSTATUS[CURTASK]=TASKST"EMPTY";
- RETURN;
- END
- RSTKPTR=TASKSTKPTR[CURTASK]; # HE REMEMBERS PLACE #
- GETCOMMON;
- MOVEWD(RSTKPTR-1,DISPRSTK,RENTSTK);
- SPREAD(RSTKPTR,RENTSTK);
- IF CURUSINTRPT THEN USRBRK=1;
- IF SHUTDOWN GR 2 THEN
- BEGIN
- USRBRK=1;
- FORCENULL=TRUE;
- END
- GENWRKNAM;
- GOTO RESUME; # TO RESUME JOB WHERE IT WAS #
- AFTERSLICE: # CONTROL MANUALLY SENT HERE BY PAUSE #
- GATHER(RSTKPTR,RENTSTK); # SAVE ALL SUBROUTINES #
- MOVEWD(RSTKPTR-1,RENTSTK,DISPRSTK);
- TASKSTATUS[CURTASK]=CHNGSTATUS;
- TASKSTKPTR[CURTASK]=RSTKPTR;
- PUTUSER;
- END
- END # OF POLLING LOOP #
- END # OF RUNJOBS #
- PAGE # INSTRUMENT -- COLLECT STATS #
- CONTROL IFEQ METERING,1;
- PROC INSTRUMENT(TYPE,DATA,DATA2);
- BEGIN
- #
- ** INSTRUMENT - TAKE STATISTICS.
- *
- * INSTRUMENT, TOGETHER WITH ENTRY POINTS INSTRMNT1,
- * INSTRMNT2, AND INSTRMNT3, COLLECTS STATISTICS REGARDING
- * INTERNAL PERFORMANCE AND WORKLOAD CHARACTERISTICS.
- *
- * ENTRY TYPE - SELECTS STATISTICAL CASE.
- * DATA - ONE DATA ITEM, WHERE APPLICABLE.
- * DATA2 - ADDITIONAL DATA WHERE REQUIRED.
- * MAXLOGGED, LOGGEDIN, TIMEOFDAY, SLICECOUNT,
- * BUILDCIO, ACCTTRANS, PALAST[0] - ADDITIONAL
- * PARAMETERS FOR CERTAIN FUNCTION TYPES.
- *
- * EXIT STATWORD[ALL] - INCREMENTED OR SET.
- * DISTRSTM, DISTTKTM, DISTCICT, DISTTRCT, DISTFLSZ,
- * DISTMGSZ - FREQUENCY DISTRIBUTIONS.
- *
- * CALLS ADDVECT.
- #
- ITEM DATA,DATA2,TYPE;
- ENTRY PROC INSTRMNT1(TYPE);
- ENTRY PROC INSTRMNT2(TYPE,DATA);
- ENTRY PROC INSTRMNT3(TYPE,DATA,DATA2);
- SWITCH INSTSW INSTTHNK,INSTRSPNS,INSTNOTTI,
- INSTNOTASK,INSTSWPE,INSTSWPD,INSTCLOCK,
- INSTPREEMPT,INSTSWPTIM,INSTEDTCIO,
- INSTSESSION,INSTTRANS,INSTXSTTO,
- INSTBREAK,INSTHANG,INSTBGNEDT,
- INSTENDEDT,INSTINPUT,INSTXMIT,
- INSTKWIK,INSTUTIL,INSTWORK,INSTDROP;
- GOTO INSTSW[TYPE];
- INSTNOTTI:
- STATWORD[1]=STATWORD[1]+1;
- RETURN;
- INSTNOTASK:
- STATWORD[2]=STATWORD[2]+1;
- RETURN;
- INSTSESSION:
- STATWORD[3]=STATWORD[3]+1;
- RETURN;
- INSTTRANS:
- STATWORD[4]=STATWORD[4]+1;
- RETURN;
- INSTRSPNS:
- STATWORD[5]=STATWORD[5]+DATA;
- ADDVECT(DISTRSTM,DATA/16);
- RETURN;
- INSTTHNK:
- STATWORD[6]=STATWORD[6]+DATA;
- ADDVECT(DISTTKTM,DATA/1024);
- RETURN;
- INSTPREEMPT: # WORDS 7, 8, 9 #
- STATWORD[6+DATA]=STATWORD[6+DATA]+1;
- RETURN;
- INSTXSTTO:
- STATWORD[10]=STATWORD[10]+1;
- RETURN;
- INSTBREAK:
- STATWORD[11]=STATWORD[11]+1;
- RETURN;
- INSTHANG:
- STATWORD[12]=STATWORD[12]+1;
- RETURN;
- INSTCLOCK:
- STATWORD[13]=MAXLOGGED;
- STATWORD[14]=LOGGEDIN;
- STATWORD[15]=TIMEOFDAY;
- STATWORD[16]=SLICECOUNT;
- RETURN;
- INSTSWPE:
- STATWORD[17]=STATWORD[17]+1;
- RETURN;
- INSTSWPD:
- STATWORD[18]=STATWORD[18]+1;
- RETURN;
- INSTSWPTIM:
- STATWORD[19]=STATWORD[19]+DATA;
- RETURN;
- INSTEDTCIO:
- STATWORD[20]=STATWORD[20]+DATA; # CIO MSECS #
- STATWORD[21]=STATWORD[21]+DATA2; # CIO COUNT #
- IF DATA2 EQ 0 THEN STATWORD[22]=STATWORD[22]+1; # NUM ZERO CIO #
- IF DATA2 GQ 16 THEN
- BEGIN
- STATWORD[23]=STATWORD[23]+1; # NUM CRUNCHERS #
- STATWORD[24]=STATWORD[24]+DATA2; # CRUNCHY EFFORT #
- END
- ADDVECT(DISTCICT,DATA2);
- RETURN;
- INSTBGNEDT:
- STATWORD[25]=STATWORD[25]+BUILDCIO; # FILEBUILD CIOS #
- RETURN;
- INSTENDEDT:
- ADDVECT(DISTTRCT,ACCTTRANS);
- ADDVECT(DISTFLSZ,PALAST[0]);
- RETURN;
- INSTINPUT:
- STATWORD[26]=STATWORD[26]+DATA; # NUM WORDS #
- RETURN;
- INSTXMIT:
- STATWORD[27]=STATWORD[27]+DATA; # NUM WORDS #
- STATWORD[28]=STATWORD[28]+DATA2; # NUM BLOCKS #
- ADDVECT(DISTMGSZ,DATA);
- RETURN;
- INSTKWIK:
- STATWORD[29]=STATWORD[29]+1;
- RETURN;
- INSTUTIL:
- STATWORD[30]=STATWORD[30]+DATA;
- RETURN;
- INSTWORK:
- STATWORD[31+DATA]=STATWORD[31+DATA]+1; # WORDS 31 THRU 41 #
- RETURN;
- INSTDROP:
- STATWORD[42]=STATWORD[42]+1;
- RETURN;
- END # OF INSTRUMENT #
- CONTROL FI;
- PAGE # USER-STATE CODE #
- # BASIC WAIT/INTERRUPT HOOKS #
- PROC SMFDLY;
- IOBEGIN(SMFDLY)
- #
- ** SMFDLY - INTERFACE FOR TASKS TO DELAY.
- *
- * EDITING CODE USE COMPILE-TIME MACROS TO REDEFINE THE
- * KEYWORD "DELAY" INTO A CALL TO "SMFDLY" FOR MULTI-USER
- * CODE. SMFDLY INTERFACES TO THE PAUSE ROUTINE, WHICH IN
- * TURN WORKS WITH RUNJOBS TO CONTROL THE TASK.
- *
- * ENTRY NO CONDITIONS.
- *
- * EXIT AFTER DELAYING.
- *
- * CALLS PAUSE.
- *
- * USES CHNGSTATUS.
- #
- CHNGSTATUS=TASKST"DELAY";
- PAUSE;
- IOEND # OF SMFDLY #
- PROC SMFRCL(AFET);
- IOBEGIN(SMFRCL)
- #
- ** SMFRCL - INTERFACE FOR TASKS TO AUTO-RECALL ON AN EVENT.
- *
- * EDITING CODE USE COMPILE-TIME MACROS TO REDEFINE THE
- * KEYWORD "RECALL" INTO A CALL TO "SMFRCL" FOR MULTI-USER
- * CODE. SMFDLY INTERFACES TO THE PAUSE ROUTINE, WHICH IN
- * TURN WORKS WITH RUNJOBS TO CONTROL THE TASK.
- *
- * NOTE THAT EDITING CODE IS NOT ALLOWED TO SPECIFY AUTO-RECALL
- * ON ANY RA+1 CALL. INSTEAD, EDITING CODE MUST ISSUE
- * RA+1 AND THEN CALL THIS ROUTINE TO RECALL UNTIL THE SYSTEM
- * FUNCTION IS COMPLETE.
- *
- * ENTRY AFET - COMPLETION WORD.
- *
- * EXIT AFTER COMPLETION BIT IS FOUND TO BE ON.
- *
- * CALLS PAUSE.
- *
- * USES CHNGSTATUS, TASKRCLADR[CURTASK].
- #
- ARRAY AFET;;
- TASKRCLADR[CURTASK]=LOC(AFET);
- CHNGSTATUS=TASKST"RECALLFET";
- PAUSE;
- IOEND # OF SMFRCL #
- PROC CLEARINT;
- IOBEGIN(CLEARINT)
- #
- ** CLEARINT - ACKNOWLEGE USER BREAK.
- *
- * EDITING CODE IS REQUIRED TO CALL THIS ROUTINE AS SOON AS
- * A USER BREAK HAS BEEN NOTICED, AND ALL EDITOR-SPECIFIC
- * RESPONSES HAVE BEEN PERFORMED. CLEARINT CLEARS FLAGS
- * INDICATING UNACKNOWLEGED INTERRUPT, SINCE ONLY EXECUTIVE
- * CODE CAN ACCESS SUCH FLAGS.
- *
- * ENTRY NO CONDITIONS.
- *
- * EXIT CURUSINTRPT - FALSE.
- * BUFFERED OUTPUT PURGED.
- * TASKREQUE - FALSE UNLESS TASK RECOVERY IN EFFECT.
- *
- * CALLS CLEARQUE.
- #
- IF CURUSINTRPT THEN TASKNXTTTO[CURTASK]=0;
- CLEARQUE;
- CURUSINTRPT=FALSE;
- IOEND # OF CLEARINT #
- PROC CLEARQUE;
- BEGIN
- #
- ** CLEARQUE - ATTEMPT TO CLEAR TASKREQUE FLAG.
- *
- * CLEARQUE CLEARS THE TASKREQUE FLAG UNLESS TASK RECOVERY IS
- * IN EFFECT. TASKREQUE IS SET BY DOINPUT WHEN A USER NEEDS
- * TO BE SCEDULED TO A TASK BUT IS ALREADY IN A TASK. DOINPUT
- * HAS NO WAY TO KNOW IF THE TASK ALREADY RUNNING WILL DETECT
- * OR IGNORE THE INPUT EVENT. THUS, THE TASKREQUE FLAG IS
- * SET. IF THE EDITING CODE NEVER USES CLEARQUE TO SHOW
- * ACKNOWLEGEMENT, THEN WHEN THE TASK SWAPS OUT THE RUNJOBS
- * ROUTINE WILL IMMEDIATELY PUT THE USER BACK IN THE SWAPIN
- * QUEUE. IF THE EDITING CODE ACKNOWLEGES THE INPUT EVENT,
- * WHICH IS USUALLY A USER BREAK, THEN CLEARQUE GETS RID OF
- * THE RESCHEDULING AT END OF TRANSACTION.
- *
- * THE TASKREQUE FLAG IS PRESERVED IF RECOVERY IS ON.
- * RECOVERY DEALS WITH JOB DETACHMENT AND SUBSYSTEM EXITS.
- *
- * ENTRY CURUSRCVRY - WHETHER RECOVERY IN EFFECT.
- * TASKREQUE[CURTASK] - WHETHER RESCHEDULING PLANNED.
- *
- * EXIT TASKREQUE[CURTASK] - UPDATED.
- #
- TASKREQUE[CURTASK]=TASKREQUE[CURTASK] AND CURUSRCVRY;
- END # OF CLEARQUE #
- PROC SPINWHEELS;
- IOBEGIN(SPINWHEELS)
- #
- ** SPINWHEELS - DELAY TASK UNTIL INPUT ARRIVES.
- *
- * SPINWHEELS ALLOWS A TASK TO HOLD ONTO ITS RESOURCES FOR
- * BRIEF TIME INTERVALS IN EXPECTATION OF A USEFUL EXTERNAL
- * ARRIVING PROBABLY WITHIN A FRACTION OF A SECOND. IF
- * RESOURCES ARE TIGHT WE TERMINATE THE WAIT SO THE CALLER CAN
- * SWAP OUT.
- *
- * ENTRY TIMEOFDAY - CURRENT TIME.
- * TASKREQUE[CURTASK], TASKTIME[CURTASK], REMAINTTI,
- * TASKAVAIL, TASKSBUSY - EVENT/RESOURCE DATA.
- * SPINTIME - TIME ALREADY SPENT SPINNING.
- *
- * EXIT TIMEOFDAY - CURRENT TIME MAY HAVE ADVANCED.
- * SPINTIME - POSSIBLY INCREMENTED.
- *
- * CALLS OKTOWAIT(INTERNAL), SMFRCL.
- *
- * USES SPINSTART, TASKPULSE[CURTASK].
- #
- FUNC OKTOWAIT B;
- BEGIN
- #
- ** OKTOWAIT - COMPUTE RULES FOR SPINWHEELS.
- *
- * OKTOWAIT DETERMINES THE EVENT/RESOURCE THRESHOLDS FOR THE
- * SPINWHEELS ROUTINES. A TASK MAY SPIN ITS WHEELS, HOLDING
- * RESOURCES, UNTIL/UNLESS ANY OF THE FOLLOWING --
- *
- * 1. THE DESIRED INPUT ARRIVES FROM IAFEX (TASKREQUE)
- *
- * 2. TWO SECONDS EXPIRE.
- *
- * 3. ONE-HALF SECOND EXPIRES AND THERE ARE MORE USERS
- * SCHEDULED FOR TASKS THAN TASKS LEFT TO TAKE THEM.
- *
- * 4. REGARDLESS OF TIMING, LESS THAN HALF OF THE TERMINAL
- * INPUT BUFFERS ARE LEFT OVER. (MOST CRITICAL RESOURCE)
- *
- * ENTRY AND EXIT - SEE OUTER PROCEDURE.
- #
- OKTOWAIT=TRUE;
- IF TASKREQUE[CURTASK] OR TIMEOFDAY-TASKTIME[CURTASK]
- GR 2000 THEN OKTOWAIT=FALSE;
- IF NUMTTIBUF-REMAINTTI GR TASKSAVAIL-TASKSBUSY AND
- TIMEOFDAY-TASKTIME[CURTASK] GR 500 THEN OKTOWAIT=FALSE;
- IF REMAINTTI LQ NUMTTIBUF/2 THEN OKTOWAIT=FALSE;
- END
- # SPINWHEELS MAIN CODE STARTS HERE #
- SPINSTART=TIMEOFDAY;
- WHYLE OKTOWAIT DO
- BEGIN
- TASKPULSE[CURTASK]=2; # SIMULATE BUSY FET #
- P<MOVTO>=LOC(TASKPULSE[CURTASK]);
- SMFRCL(MOVTO); # APPROX 05-HZ DELAY LOOP #
- END
- SPINTIME=SPINTIME+TIMEOFDAY-SPINSTART;
- IOEND # OF SPINWHEELS #
- PAGE # RELIABILITY/METERING HOOKS #
- PROC FATALTRAP;
- IOBEGIN(FATALTRAP)
- #
- ** FATALTRAP - INTERFACE FOR FAILING TASKS.
- *
- * FATALTRAP IS CALLED BY EDITING CODE WHICH DETECTS ITS OWN
- * UNCORRECTABLE ALGORITHMIC INCONSISTENCY. THIS INTERFACE
- * WAITS FOR ANY CIO CALL TO FINISH THEN BRANCHES DIRECTLY
- * TO THE RUNJOBS EXECUTIVE.
- *
- * ENTRY FET - MAYBE ACTIVE.
- *
- * EXIT FET - COMPLETE.
- * VIA AFTEREDIT LABEL.
- *
- * CALLS SMFRCL, AFTEREDIT.
- #
- XREF LABEL AFTEREDIT;
- SMFRCL(FET); # WAIT IO DONE #
- GOTO AFTEREDIT; # TERMINATE TASK #
- END # OF FATALTRAP #
- PROC ABTPAUSE;
- IOBEGIN(ABTPAUSE)
- #
- ** ABTPAUSE - TRY TO CHECKPOINT WORKFILE AFTER ABORT.
- *
- * ABTPAUSE IS CALLED AS EDITING CODE BY THE RUNJOBS EXECUTIVE
- * WHEN A TASK HAS ABORTED ITSELF. THE INTENT IS TO ATTEMPT
- * TO CHECKPOINT THE WORKFILE BEFORE TRANSITIONING BACK TO
- * SINGLE-USER. IF THIS CAN BE DONE, THEN THE SINGLE EDITOR
- * WILL DETECT THE ABORTED FLAG IN THE DATA SEGMENT OF THE
- * WORKFILE AND WILL KNOW THAT IT CANNOT PROCEED. ABTPAUSE
- * MAY NOT SUCCEED, AND RUNJOBS IS RESPONSIBLE TO KEEP TRACK
- * OF ABTPAUSE FAILURE AND INSTEAD CALL ABTKILL.
- *
- * CALLS PAUSEIO.
- #
- PAUSEIO;
- IOEND # OF ABTPAUSE #
- PROC ABTKILL;
- IOBEGIN(ABTKILL)
- #
- ** ABTKILL - KILL OFF TASK AFTER DOUBLE ABORT.
- *
- * THE RUNJOBS EXECUTIVE CALLS ABTKILL AS A LAST RESORT WHEN A
- * TASK HAS DELIBERATELY ABORTED ITSELF, THEN HAS ABORTED
- * ITSELF A SECOND TIME WHEN ABTPAUSE ATTEMPTED TO CHECKPOINT
- * THE WORKFILE. ABTKILL ATTEMPTS TO ZAP THE WORKFILE TO
- * CONTAIN EXACTLY ONE WORD OF ZEROES, WHICH WOULD NOT BE
- * ACCEPTED AS A VALID TRANSITION ONCE THE SINGLE-USER EDITOR
- * GETS BACK IN CONTROL. THE INTENT IS TO BE AS CERTAIN AS
- * POSSIBLE THAT THE SINGLE EDITOR WILL NOT PICK UP AND
- * CONTINUE A HOPELESS EDIT SESSION.
- *
- * CALLS SMFRCL, WRITEO, REWRITR, SMFRCL.
- *
- * USES FET.
- #
- SMFRCL(FET);
- FETRR=1;
- WRITEO(FET,0);
- REWRITR(FET,0);
- SMFRCL(FET);
- IOEND # OF ABTKILL #
- CONTROL IFEQ METERING,1;
- PROC BGNMETER;
- BEGIN
- #
- ** BGNMETER - INSTRUMENT BEGINNING OF EDIT SESSION.
- *
- * BGNMETER ALLOWS THE SINGLE-USER EDITOR TO PASS DATA FROM
- * ITS FILE-BUILD PROCESS, INTO THE CORRESPONDING TASK IN
- * THE MULTI-USER EDITOR, WHICH CAN USE THIS INTERFACE TO
- * GLOBALLY RECORD THE DATA.
- *
- * CALLS INSTRMNT1.
- #
- INSTRMNT1(INSTST"BGNEDT");
- END
- PROC WIOSTAT(ORDINAL);
- BEGIN
- #
- ** WIOSTAT - WORKIO STATISTICS INTERFACE.
- *
- * WIOSTAT IS CALLED BY THE WORKFILE MANAGER AT NOTEWORTHY
- * EVENTS SO THAT STATISTICS CAN BE INCREMENTED.
- *
- * ENTRY ORDINAL - WHICH ACCUMULATOR TO INCREMENT.
- *
- * CALLS INSTRMNT2.
- #
- ITEM ORDINAL;
- INSTRMNT2(INSTST"WORKIO",ORDINAL);
- END
- CONTROL FI;
- PAGE # FNT MANAGEMENT #
- PROC RTRNWRKFIL;
- IOBEGIN(RTRNWRKFIL)
- #
- ** RTRNWRKFIL - RETURN THE WORKFILE FNT.
- *
- * BEFORE SMFEX CAN TRANSITION A USER BACK TO THE SINGLE
- * USER EDITOR, IT MUST GET RID OF ITS LOCAL FNT FOR THE
- * USERS WORKFILE. RTRNWRKFIL DOES THIS AND IS
- * DESIGNED TO BE CALLED BY RUNJOBS IN USER STATE JUST AFTER
- * THE TASK HAS TERMINATED AT THE AFTEREDIT LABEL.
- *
- * ENTRY FET - SETUP.
- *
- * EXIT CURUSDONE - TRUE.
- *
- * CALLS RETERN, SMFRCL.
- #
- RETERN(FET,0);
- CURUSDONE=TRUE; # ASSURE NO RECOVERY #
- SMFRCL(FET);
- IOEND # OF RTRNWRKFIL #
- PAGE # LOGIN/LOGOUT CONTROL #
- PROC SENDLOGOUT;
- IOBEGIN(SENDLOGOUT)
- #
- ** SENDLOGOUT - TRANSMIT LAST OUTPUT AND ROLLIN SINGLE.
- *
- * SENDLOGOUT PERFORMS THE LAST PROCESSING WHEN A TASK
- * COMPLETES ALL MULTI-USER PROCESSING. SENDLOGOUT SHOULD
- * BE CALLED ONLY BY RUNJOBS AFTER THE TASK HAS EXITED
- * AT LABEL AFTEREDIT AND AFTER THE WORKFILE LOCAL FNT HAS
- * BEEN RETURNED. SENDLOGOUT ASSURES THAT ANY OUTPUT LEFT
- * IN OUR BUFFERS IS SEND ON TO IAF, THEN TELLS IAF THE
- * USER IS LEAVING MULTI-USER MODE, THEN ISSUES AN EESET
- * FUNCTION TO CAUSE ROLLIN OF THE SINGLE USER JOB.
- *
- * THE TLX FUNCTION USED BY THE SINGLE USER JOB TO ROLLOUT
- * WILL BE RECALLED TO VERIFY THAT SMFEX HAS PROPERLY
- * DISPENSED WITH THE WORKFILE. TLX THEN CONFORMS TO IAF
- * THAT THE MULTI-USER SESISON IS OVER.
- *
- * ENTRY TASKNXTTTO[CURTASK] - INDICATES RESIDUAL OUTPUT.
- *
- * EXIT TASKNXTTTO[CURTASK] - ZERO.
- *
- * CALLS TTOTRAP, TRANSMIT, EESET.
- *
- * USES TTOADDR, TTOLEN, TTOTYPE.
- #
- IF TASKNXTTTO[CURTASK] NQ 0 THEN
- BEGIN
- TTOADDR=0;
- TTOLEN=0;
- TTOTYPE=TTOST"FORCE";
- TTOTRAP;
- END
- TASKTYPTTO[CURTASK]=SMF2IAF"LOGOUT";
- TRANSMIT;
- EESET((TTEQ*4096)+USEREJT[CURUSER]);
- IOEND # OF SENDLOGOUT #
- PAGE # TRANSMIT TO IAFEX #
- PROC TRANSMIT;
- IOBEGIN(TRANSMIT)
- #
- ** TRANSMIT - TRANSMIT A FUNCTION CODE/MESSAGE TO IAFEX.
- *
- * TRANSMIT IS USED FOR THE ISSUANCE OF ALL CODES TO IAFEX
- * EXCEPT FOR THE SPECIAL CASE WHERE DOINPUT NEEDS TO
- * DISCONNECT A TERMINAL IN SERIALIZED OPERATION FOR
- * OVERFLOWED TABLES. TRANSMIT EXECUTES IN USER MODE, THUS
- * THE EXECUTIVE HAS NO WAY TO SEND MESSAGES TO IAFEX EXCEPT
- * FOR THE CASE ALREADY MENTIONED.
- *
- * EACH TASK HAS ITS OWN OUTPUT BUFFER WHICH IS USED TO
- * ACCUMULATE AND BATCH OUTPUT TEXT TOGETHER TO MINIMIZE CALLS
- * TO TRANSMIT. ONCE TRANSMIT IS CALLED, IT USES THE SCP/UCP
- * FACILITY TO SEND THE TASK'S BUFFER TO IAF. IF THE SCP/UCP
- * FUNCTIONS INDICATE THAT THE MESSAGE COULD NOT BE SENT TO
- * IAF ON THIS RECALL CYCLE, THEN THE TASK IS DELAYED
- * (ALLOWING OTHER TASKS TO EXECUTE IN PARALLEL) AND THE
- * SCP/UCP OPERATION WILL BE TRIED AGAIN.
- *
- * ENTRY TASKTYPTTO[CURTASK] - FUNCTION CODE FOR IAFEX.
- * TASKNXTTO[CURTASK] - AMOUNT OF TEXT TO GO WITH
- * FUNCTION CODE.
- * CURUSIAFNUM - IAFEX TERMINAL NUMBER.
- * TTOWORDS, TTOBLOCKS - STATISTICAL ACCUMULATORS.
- * CURUSLASTIM, TIMEOFDAY - ALSO FOR STATISTICS.
- * CURUSRCVRY, CURUSINTRPT - INDICATE PURGE BUFFER.
- *
- * EXIT TTOWORDS, TTOBLOCKS - INCREMENTED.
- * CURUSLASTIM, TIMEOFDAY - UP TO DATE.
- *
- * CALLS MELT, SYSTEM, INSTRMNT2, SMFDLY.
- *
- * USES IAFHEADER, P<SSCBUFFER>.
- #
- ITEM TMP1;
- TRCSTR("NTR TRSMT$");
- CONTROL IFEQ TRACEFLAG,1;
- TMP1=TASKNXTTTO[CURTASK];
- TRACEBOTH("NXTTTO$",TMP1);
- TMP1=TASKTYPTTO[CURTASK];
- TRACEBOTH("TYPTTO$",TMP1);
- CONTROL FI;
- CONTROL IFGQ PARANOIA,2;
- IF TASKNXTTTO[CURTASK] GR SIZTTOBUF THEN MELT("TRANSMIT 1$");
- IF CURUSIAFNUM GR MAXCONNECT THEN MELT("TRANSMIT 2$");
- CONTROL FI;
- IF CURUSINTRPT OR CURUSRCVRY THEN
- BEGIN
- TASKNXTTTO[CURTASK]=0;
- IF SHUTDOWN EQ 2 OR TASKTYPTTO[CURTASK] EQ SMF2IAF"MSGOUT" OR
- TASKTYPTTO[CURTASK] EQ SMF2IAF"PROMPT" THEN
- BEGIN
- TASKTYPTTO[CURTASK]=0;
- IORET
- END
- END
- IAFFUNC=TASKTYPTTO[CURTASK];
- IAFLEN=TASKNXTTTO[CURTASK]+1;
- IAFPTR=0;
- IAFTERM=CURUSIAFNUM;
- TTOBUFF[1]=IAFHEADER;
- CONTROL IFEQ METERING,1;
- TTOWORDS=TTOWORDS+IAFLEN;
- TTOBLOCKS=TTOBLOCKS+1;
- CONTROL FI;
- TRYTOSEND: # BACK HERE IF RETRY NEEDED #
- TTOBUFF[0]=0;
- P<SSCBUFFER>=LOC(TTOBUFFER);
- SSCTYPE=O"3";
- SSCCOUNT=IAFLEN;
- SYSREQ("SSC",0,LOC(SSCBUFFER),IAFSSID);
- IF SSCSTATUS LAN O"7776" EQ 0 THEN # NO ERROR #
- BEGIN
- CONTROL IFEQ TRACEFLAG,1;
- ITEM TMP2,TMP3;
- IAFHEADER=TTOBUFF[1]; # SINCE MAY HAVE LOST CTL #
- TMP1=IAFFUNC;
- TMP2=IAFTERM;
- TMP3=IAFLEN-1;
- P<MOVFROM>=LOC(TTOBUFF[2]);
- TRACEBOTH("FUNCOUT$",TMP1);
- TRACEDEC(TMP2);
- IF IAFLEN GR 1 THEN TRACEWORDS(MOVFROM,TMP3);
- CONTROL FI;
- CONTROL IFEQ METERING,1;
- IF NOT CURUSOLDSND THEN
- BEGIN
- TMP1=TIMEOFDAY-CURUSLASTIM;
- INSTRMNT2(INSTST"RSPNS",TMP1);
- END
- CONTROL FI;
- IF TASKTYPTTO[CURTASK] EQ SMF2IAF"MSGOUT" THEN CURUSOLDSND=TRUE;
- ELSE CURUSOLDSND=FALSE;
- CURUSLASTIM=TIMEOFDAY;
- IORET
- END
- ELSE IF SSCSTATUS LAN O"7776" EQ 4 THEN # IAF BUSY NOW #
- BEGIN
- SMFDLY;
- GOTO TRYTOSEND;
- END
- ELSE MELT("CANT TALK TO IAFEX$");
- IOEND # OF TRANSMIT #
- PAGE # VOLUNTEER TO SURRENDER TASK #
- PROC VOLUNTEER;
- IOBEGIN(VOLUNTEER)
- #
- ** VOLUNTEER - SEE IF THIS TASK SHOULD SLOW DOWN.
- *
- * VOLUNTEER IS USED TO PREVENT A TASK FROM EXCESSIVE RESOURCE
- * USAGE. EDITING CODE SHOULD CALL VOLUNTEER PERIODICALLY
- * INSIDE ANY PROCESS WHICH IS POTENTIALLY LONG-RUNNING. NOTE
- * THAT ANY CODE IN THE WORKFILE MANAGER (THE WORKIO MODULE)
- * IS A "MUST COMPLETE" FUNCTION - THAT MEANS THAT VOLUNTEER
- * CAN BE CALLED BY ACTUAL EDITING CODE BUT CANNOT BE CALLED
- * FROM WORKIO ITSELF.
- *
- * VOLUNTEER FIRST CONSIDERS WHETHER THE TASK IS USING
- * EXCESSIVE CPU TIME ON AN INSTANTANEOUS BASIS. THE
- * OPERATING SYSTEM REAL TIME MILLISECOND CLOCK IS FRESHLY
- * ACCESSED, AND THE CURRENT TIME IS COMPARED TO THE TIME
- * TAKEN AT THE START OF THE RECALL CYCLE TO SEE IF MORE THAN
- * A FEW MILLISECONDS OF CPU HAVE BEEN USED. A CALCULATION
- * ATTEMPTS TO SELECT A THRESHOLD SUCH THAT SMFEX WILL NEVER
- * USE MORE THAN ABOUT HALF OF THE CPU. THIS MEANS THAT FOR
- * AN INSTALLATION WHICH INTENDS THAT SUBSTANTIALLY ALL OF THE
- * CPU SHOULD BE USED FOR TEXT EDITING, SMFEX MAY BE
- * UNSUITABLE AND THE SINGLE-USER EDITORS MAY BE BETTER.
- *
- * IF THE TASK IS CURRENTLY USING MORE THAN A FEW MILLISECONDS
- * OF CPU, IT DELAYS, AND THE REMAINDER OF THE VOLUNTEER
- * ALGORITHM WILL CONTINUE ON A LATER RECALL CYCLE.
- *
- * THE REMAINDER OF THE VOLUNTEER ALGORITHM CONSIDERS WHETHER
- * A TASK HAS RESIDED IN ITS SWAPPED-IN MEMORY IMAGE FOR TOO
- * MUCH REAL TIME. WE CALCULATE THE REAL TIME FROM THE TIME
- * AT WHICH THE TASK SWAPPED IN UNTIL THE PRESENT TIME. IF
- * THE TIME DELTA EXCEEDS THE "VOLTIME" THRESHOLD AND THERE IS
- * QUEUED TERMINAL OUTPUT, THE TASK WILL SWAP OUT SO THE
- * OUTPUT CAN BE SENT. IF THE TIME DELTA EXCEEDS THE
- * THRESHOLD AND THERE ARE MORE USERS AWAITING SWAPIN THAN THE
- * NUMBER OF TASKS FREE TO SWAP THEM IN, THEN THIS TASK WILL
- * SWAPOUT SO ANOTHER USER CAN SWAPIN. IF THE NUMBER OF
- * TERMINAL INPUT BUFFERS IS DOWN TO APPROXIMATELY ONE FOURTH
- * OF THE TOTAL, THEN THIS TASK WILL SWAP OUT REGARDLESS OF
- * WHETHER WE HAVE EXCEEDED THE THRESHOLD.
- *
- * THUS, THE "VOLTIME" THRESHOLD REPRESENTS THE AMOUNT OF TIME
- * A TASK IS ASSURED THAT IT CAN REMAIN SWAPPED IN. IF THE
- * TASK IS NOT PRODUCING OUTPUT AND THERE IS NO EXCESS QUEUE
- * FOR SWAPIN, THE TASK CAN EXCEED THE TRESHOLD. BUT IF THERE
- * IS A CRITICAL RESOURCE SHORTAGE (INPUT BUFFERS) THEN ALL
- * BETS ARE OFF AND WE SWAP THIS TASK AS SOON AS IT HAS
- * VOLUNTEERED, WITHOUT ALLOWING THE NORMAL GUARANTEED TIME.
- *
- * ENTRY TIMEOFDAY - TIME AT WHICH THIS RECALL CYCLE STARTED.
- * OLDTIMEDAY - TIME FOR START OF PREVIOUS RECALL CYCLE,
- * OR TIME OF VOLUNTEER EXECUTION WITHIN PREVIOUS
- * RECALL CYCLE IF VOLUNTEER WAS CALLED.
- * TASKTIME[CURTASK] - WHEN THIS TASK SWAPPED IN.
- * TASKNXTTTO[CURTASK] - WHETHER OUTPUT IS PENDING.
- * TASKSAVAIL - TOTAL USABLE TASKS.
- * TASKSBUSY - NUMBER OF TASKS USED NOW.
- * SWPQSIZE - NUMBER OF USERS AWAITING SWAPIN.
- * REMAINTTI - NUMBER OF UNUSED INPUT BUFFERS.
- *
- * EXIT TIMEOFDAY - UP TO DATE.
- * TASKNXTTTO[CURTASK] - CLEARED IF SWAPPED.
- * TASKTIME[CURTASK] - NEW VALUE IF SWAPPED.
- * CURUSCRUNCH - TRUE IF SWAP FOR OVERTIME BUT NO OUTPUT.
- * TASKREQUE[CURTASK] - TRUE IF SWAP NOT FOR OUTPUT.
- *
- * CALLS RTIME, MIN, MAX, SMFDLY, INSTRMNT1, INSTRMNT2,
- * TTSYNC, TTOTRAP.
- *
- * USES TTOADDR, TTOLEN, TTOTYPE.
- #
- ITEM DELTA, SURRENDER;
- RTIME(NEWTIMEDAY);
- NEWTIMEDAY=B<24,36>NEWTIMEDAY;
- DELTA=MAX(50,MIN(10,(TIMEOFDAY-OLDTIMEDAY)/2));
- IF NEWTIMEDAY-TIMEOFDAY GR DELTA THEN
- BEGIN
- SMFDLY;
- CONTROL IFEQ METERING,1;
- INSTRMNT1(INSTST"DROPCPU");
- CONTROL FI;
- END
- # NEXT CODE IS NON-REENTRANT, MUST RUN INSTANTANEOUSLY #
- DELTA=TIMEOFDAY-TASKTIME[CURTASK];
- SURRENDER=0;
- # TRY TO MOVE IF SITTING ON TYPABLE OUTPUT FOR A LONG TIME #
- IF TASKNXTTTO[CURTASK] NQ 0 AND DELTA GQ VOLTIME*4
- THEN SURRENDER=1;
- # ALSO TRY TO MOVE IF SHORT ON TASKS FOR A SHORT TIME #
- IF TASKSAVAIL-TASKSBUSY LS SWPQSIZE AND DELTA GQ VOLTIME
- THEN SURRENDER=2;
- # MOVE IF CRITICAL RESOURCE SHORTAGE REGARDLESS OF TIME #
- IF REMAINTTI LQ (NUMTTIBUF+3)/4
- THEN SURRENDER=3;
- # END OF INSTANTANEOUS ALGORITHM #
- IF SURRENDER NQ 0 THEN # FACE WRITING ON WALL #
- BEGIN
- TRCBOTH("PREEMPT$",CURUSER);
- CONTROL IFEQ METERING,1;
- INSTRMNT2(INSTST"PREEMPT",SURRENDER);
- CONTROL FI;
- IF SCREENMODE THEN
- BEGIN # IF IN SCREEN MODE #
- VDSYNCH; # MUST PRECEED TASKNXTTTO CHECK #
- END # SINCE OUTPUT MAY BE FLUSHED #
- ELSE
- BEGIN # LINE MODE #
- TTSYNC; # MUST PRECEED TASKNXTTTO CHECK #
- END # SINCE OUTPUT MAY BE FLUSHED #
- IF TASKNXTTTO[CURTASK] EQ 0 THEN
- BEGIN # IF NO OUTPUT QUEUED FOR USER #
- CURUSCRUNCH=TRUE; # NO OUTPUT, JUST CRUNCHING #
- TASKREQUE[CURTASK]=TRUE; # SHOULD BE REQUEUED #
- END
- TTOADDR=0;
- TTOLEN=0;
- TTOTYPE=TTOST"FORCE";
- TTOTRAP;
- END
- IOEND # OF VOLUNTEER #
- PAGE # TTY INPUT HOOK #
- PROC TTITRAP;
- IOBEGIN(TTITRAP)
- #
- ** TTITRAP - PROVIDE EDITOR CODE WITH INPUT TEXT.
- *
- * TTITRAP IS CALLED BY THE EDITOR IN LIEU OF CIO READ
- * FUNCTIONS AGAINST AN INPUT FET. CALLING TTITRAP INSTEAD OF
- * CIO IS DONE BY CONDITIONAL COMPILATION OF CODE IN THE
- * TERMIO MODULE. THE EDITOR IS NOT ALLOWED TO OBTAIN INPUT
- * BY ANY MEANS EXCEPT TO CALL TERMIO AND LET IT DECIDE WHICH
- * MECHANISM IS APPROPRIATE FOR THE VERSION OF THE EDITOR.
- *
- * IN ADDITION TO PROVIDING INPUT, TTITRAP ALSO PROVIDES A
- * MEANS TO PURGE ANY UNUSED INPUT FROM THE BUFFERS CHAINS.
- * THIS IS INDICATED BY A NEGATIVE VALUE IN THE TTILEN
- * PARAMETER.
- *
- * WHEN INPUT IS DESIRED, TERMIO USES A POSITIVE VALUE IN THE
- * TTILEN PARAMETER TO INDICATE THE MAXIMUM NUMBER OF WORDS IT
- * CAN ACCEPT. THE WORKING BUFFER IS POINTED TO BY THE
- * TTIADDR PARAMETER. THE TTINEXT PARAMETER IS MAINTAINED BY
- * THIS ROUTINE TO KEEP TRACK OF WHAT PORTIONS OF THE CURRENT
- * BUFFER CHAIN HAVE ALREADY BEEN TRANSMITTED.
- *
- * INPUT FROM IAFEX IS MAINTAINED BY SMFEX, UNTIL TTITRAP IS
- * READY TO PASS ON TO THE EDITING CODE, IN A CHAIN OF ONE OR
- * MORE TERMINAL INPUT BUFFERS. ONE BUFFER IS CHAINED FOR
- * EACH MESSAGE FRAGMENT SENT BY IAFEX. TTITRAP MAINTAINS THE
- * TTILAST PARAMETER, WHICH IS THE TEXT OF THE LAST WORD
- * PASSED TO TERMIO, TO KNOW WHETHER THE PREVIOUS TTITRAP
- * CYCLE ENCOUNTERED A ZERO BYTE TERMINATOR. THIS ENABLES
- * TTITRAP TO KNOW WHETHER THE EDITING TASK IS IN THE MIDDLE
- * OF A SERIES OF FRAGMENTS OR IS AWAITING THE FIRST FRAGMENT
- * OF A MESSAGE.
- *
- * IF TTITRAP DETERMINES THAT THE TASK IS IN THE MIDDLE OF A
- * SERIES OF FRAGMENTS, BUT DOES NOT YET HAVE THE NEXT
- * FRAGMENT FROM IAFEX, TTITRAP WILL ATTEMPT TO KEEP THE TASK
- * DELAYING IN MEMORY, USING THE SPINWHEELS FUNCTION. THIS IS
- * DONE BECAUSE THERE IS AN EXCELLENT PROBABILITY THAT THE
- * NEXT INPUT FRAGMENT WILL ARRIVE FROM IAFEX WITHIN A FEW
- * MILLISECONDS. ON THE OTHER HAND, WHEN THE EDITING TASK
- * ASKS FOR THE FIRST FRAGMENT OF A MESSAGE AND NO TEXT HAS
- * ARRIVED YET FROM IAFEX, IT IS LIKELY THAT SEVERAL SECONDS
- * WILL PASS BEFORE THE INPUT ARRIVES, SO THAT TASK IS ALLOWED
- * TO SWAPOUT.
- *
- * ONCE THE TASK ADVANCES THRU TTITRAP BEYOND ANY WHEELSPIN OR
- * ANY SWAPOUT, TTITRAP ASSEMBLES AS MUCH INPUT TEXT AS IT
- * CAN, UNTIL EITHER THE TTILEN PARAMETER IS EXHAUSTED OR THE
- * END OF ONE BUFFER IS REACHED. TEXT FROM THE NEXT BUFFER OF
- * A CHAIN OF SEVERAL FRAGMENTS CANNOT BE PROCESSED UNTIL THE
- * NEXT CALL TO TTITRAP. THIS MEANS THAT THE SIZE OF EACH
- * FRAGMENT ALLOWED BY IAFEX AND SMFEX MUST BE ADEQUATE FOR
- * COMPLETE INPUTS WHEN THE EDITOR IS USED IN LINE MODE. THIS
- * RESTRICTION IS IN EFFECT BECAUSE THE LINE EDITOR REQUESTS
- * INPUT IN COMPLETE LINE IMAGES. THE SCREEN EDITOR, HOWEVER,
- * ASKS FOR INPUT ONE WORD AT A TIME, SO MULTIPLE FRAGMENTS
- * CAN BE PROCESSED WITH MULTIPLE TTITRAP CALLS.
- *
- * WHEN TTITRAP DECIDES TO SWAP THE TASK OUT, IT CALLS PAUSEIO
- * IN THE WORKFILE MANAGER. THIS IS DONE BECAUSE WORKIO HOLDS
- * SOME TRANSIENT RESOURCES, SUCH AS ITS CIRCULAR BUFFER, AND
- * NEEDS THE OPPORTUNITY TO COMPLETE ITS USAGE OF THESE
- * RESOURCES.
- *
- *
- * ENTRY TTILEN - NEGATIVE MEANS PURGE UNUSED INPUT.
- * POSITIVE IS TASKS CAPACITY FOR TEXT.
- * TTIADDR - WHERE THE TEXT SHOULD GO.
- * CURUSTTIBUF - FIRST BUFFER LINKAGE.
- * TTINEXT - WHERE TTITRAP PREVIOUS EXTRACTED TEXT.
- * TTILAST - LAST WORD OF TEXT FROM PREVIOUS TTITRAP.
- * RUNTIME - FOR STATISTICS.
- * TIMEOFDAY, TASKTIME[CURTASK] - FOR STATISTICS.
- * ACCTCIO, ACCTTRANS - STATISTICS/ACCOUNTING.
- * TTOWORDS, TTOBLOCKS - FOR STATISTICS.
- * TTIBUFADDR[ALL] - SETUP.
- * TTIBUFLNK[ALL] - LINKAGES.
- * TTIBUFLEN[ALL] - FRAGMENT SIZES.
- * TTIBITS - ALLOCATION BITMASK FOR BUFFERS.
- *
- * EXIT TTINEXT - INCREMENTED.
- * CURUSTTIBUF - ADVANCED/CLEARED VIA LINKAGE.
- * TIMEOFDAY - UP TO DATE.
- * TASKTIME[CURTASK] - TIME OF SWAPOUT IF ANY.
- * RUNTIME, ACCTCIO, ACCTTRANS - INCREMENTED.
- * SPINTIME, RUNTIME, CIOCOUNT - CLEARED IF SWAPPED.
- * CURUSOKOUT - TRUE.
- * TTILEN - DECREMENTED.
- * TTILAST - UPDATED.
- * REMAINTTI - INCREMENTED IF BUFFER EMPTIED.
- * TTOWORDS, TTOBLOCKS - CLEARED IF SWAPPED.
- *
- * CALLS PURGETTI, SPINWHEELS, CLEARQUE, PAUSEIO, INSTRMNT1,
- * INSTRMNT2, INSTRMNT3, TTOTRAP, MIN, MOVEWD, DEALLOC.
- *
- * USES TTOLEN, TTOTYPE.
- #
- ITEM TMP1, TMP2, TMP3;
- ITEM QUESTION1 I=O"7100 0013 0000 0000 0000"; # PROMPT ONE #
- ITEM QUESTION2 I=O"7155 0013 0000 0000 0000"; # PROMPT TWO #
- ITEM XPTINCTL I=O"0006 4704 0015 0000 0000"; # XPARENT INPUT #
- TRCSTR("NTR ITRP$");
- IF TTILEN LS 0 THEN # PURGE ANY BUFFERS #
- BEGIN
- IF CURUSTTIBUF NQ 0 THEN PURGETTI;
- TTINEXT=0;
- IORET
- END
- IF CURUSTTIBUF EQ 0 AND B<48,12>TTILAST NQ 0 THEN
- BEGIN # DELAY SINCE MORE INPUT DUE ASAP #
- SPINWHEELS; # DELAY TILL INPUT ARRIVES OR TIMEOUT #
- CLEARQUE;
- END
- IF NOT CURUSOKOUT THEN # FIRST TRANSACTION #
- BEGIN
- CURUSOKOUT=TRUE;
- IF SCREENMODE THEN
- BEGIN
- ROWPAINT[COMMANDROW]=TRUE;
- END
- ELSE
- BEGIN
- TTOADDR=LOC(QUESTION1);
- TTOLEN=1;
- TTOTYPE=TTOST"NORMAL";
- TTOTRAP;
- END
- END
- IF CURUSTTIBUF EQ 0 THEN # NORMAL TRANSACTION SO SWAPOUT #
- BEGIN
- PAUSEIO; # LET WORKIO PP'S DROP #
- RUNTIME=TIMEOFDAY-TASKTIME[CURTASK]+RUNTIME;
- TASKTIME[CURTASK]=TIMEOFDAY;
- ACCTCIO=ACCTCIO+CIOCOUNT;
- ACCTTRANS=ACCTTRANS+1;
- CONTROL IFEQ METERING,1;
- INSTRMNT2(INSTST"TASKUTIL",RUNTIME);
- INSTRMNT3(INSTST"EDTCIO",RUNTIME-SPINTIME,CIOCOUNT);
- INSTRMNT1(INSTST"TRANS");
- CONTROL FI;
- IF NOT CURUSINTRPT THEN
- BEGIN # NO FRESH BREAK, CAN PROMPT #
- TTOADDR=LOC(QUESTION2);
- TTOLEN=1;
- IF SCREENMODE THEN # IF SCREEN MODE #
- BEGIN
- IF TABTYPHEAD[0] THEN TTOLEN=0; # IF TYPEAHEAD USED #
- ELSE TTOADDR=LOC(XPTINCTL); # NO TYPEAHEAD #
- END
- TTOTYPE=TTOST"PROMPT";
- TTOTRAP;
- END
- SPINTIME=0;
- RUNTIME=0;
- CIOCOUNT=0;
- CONTROL IFEQ METERING,1;
- INSTRMNT3(INSTST"XMIT",TTOWORDS,TTOBLOCKS);
- TTOBLOCKS=0;
- TTOWORDS=0;
- CONTROL FI;
- END
- # NOW WE KNOW WE HAVE SOMETHING #
- MEM[TTIADDR]=0; # ASSURE DEFAULT NULL LINE #
- WHYLE CURUSTTIBUF NQ 0 AND TTILEN GR 0 DO
- BEGIN
- TMP1=CURUSTTIBUF;
- P<MOVFROM>=TTIBUFADDR[TMP1]+TTINEXT;
- P<MOVTO>=TTIADDR;
- TMP2=TTIBUFLEN[TMP1]-TTINEXT;
- TMP3=MIN(TMP2,TTILEN);
- MOVEWD(TMP3,MOVFROM,MOVTO);
- TTINEXT=TTINEXT+TMP3; # INCREMENT SOURCE ADDR #
- TTILEN=TTILEN-TMP3; # DECREMENT CALLERS COUNT #
- TTILAST=MEM[LOC(MOVFROM)+TMP3-1]; # SHOWS WHETHER EOL SEEN #
- IF TTINEXT GQ TTIBUFLEN[TMP1] THEN
- BEGIN # RELEASE THIS BUFFER, POINT NEXT #
- TTINEXT=0;
- DEALLOC(TTIBITS,TMP1,NUMTTIBIT);
- REMAINTTI=REMAINTTI+1;
- CURUSTTIBUF=TTIBUFLNK[TMP1];
- END
- END
- IOEND # OF TTITRAP #
- PAGE # TTY OUTPUT AND SWAPOUT HOOK #
- PROC TTOTRAP;
- IOBEGIN(TTOTRAP)
- #
- ** TTOTRAP - QUEUE/ISSUE OUTPUT, SWAP AS NEEDED.
- *
- * TTOTRAP IS CALLED BY EDITOR CODE IN LIEU OF CIO WRITE
- * FUNCTIONS AGAINST AN OUTPUT FET. EDITING CODE IS REQUIRED
- * TO INTERFACE ALL OUTPUT THRU THE TERMIO MODULE, WHICH USES
- * CONDITIONAL COMPILATION TO SELECT THE RIGHT TECHNIQUE OF
- * OUTPUT FOR THE VERSION OF THE EDITOR.
- *
- * TTOTRAP IS ALSO USED BY THE VOLUNTEER AND TTITRAP ROUTINES
- * OF SMFEX. TTOTRAP PROVIDES SWAPOUT LOGIC FOR THOSE CALLERS
- * TOGETHER WITH ISSUANCE OF RESIDUAL OUTPUT.
- *
- * TTOTRAP IS CONTROLLED PRIMARILY BY THE TTOTYPE PARAMETER.
- * THE "NORMAL" VALUE INDICATES THAT THE CALLER'S INTENT IS TO
- * OFFER SOME OUTPUT TEXT. TTOTRAP QUEUES THIS TEXT INTO THE
- * TASK'S UNIQUE OUTPUT BUFFER AS POSSIBLE, CALLING THE
- * TRANSMIT ROUTINE TO SEND TO IAFEX WHENEVER THE BUFFER IS
- * FULL. FOR THIS TYPE OF COMMUNICATION TO IAFEX, TTOTRAP
- * THEN USES THE SPINWHEELS FUNCTION TO HOLD ONTO THE TASK FOR
- * A FEW EXTRA MILLISEONDS, SINCE THERE IS ABOUT AN EVEN
- * CHANCE THAT IAFEX WILL QUICKLY RESPOND AND ASK SMFEX TO
- * CONTINUE TASK EXECUTION. IF IAFEX FAILS TO RESPOND WITHIN
- * THE LIMITATIONS OF THE SPINWHEELS ROUTINE, THEN TTOTRAP
- * ASSUMES IT WILL BE SEVERAL SECONDS BEFORE IAFEX AND THE
- * NETWORK CAN ACCEPT ANY OTHER OUTPUT FOR THIS USER, AND
- * TTOTRAP SWAPS THE TASK OUT.
- *
- * THE SECOND BASIC VALUE FOR THE TTOTYPE PARAMETER IS
- * "PROMPT". THIS IS USED WHEN TTITRAP CALLS TTOTRAP.
- * TTOTRAP IS EXPECTED TO IMMEDIATELY TRANSMIT ANY RESIDUAL
- * QUEUE OF OUTPUT TEXT TO IAFEX, THEN SWAP THE TASK OUT.
- * TTOTRAP ASSUMES THAT THE CALLER (TTITRAP) HAS ALREADY MADE
- * A DETERMINATION AS TO LOW PROBABILITY OF RAPID REPLY FROM
- * IAFEX.
- *
- * THE THIRD AND LAST BASIC FUNCTION OF TTOTRAP IS THE "FORCE"
- * VALUE OF THE TTOTYPE PARAMETER. THIS IS USED BY VOLUNTEER
- * WHEN IT IS DETERMINED THAT SOME RESIDUAL TEXT HAS BEEN
- * QUEUED IN THE TASK'S OUTPUT BUFFER FOR AN EXCESSIVE REAL
- * TIME DELAY, AND OUGHT TO BE SENT TO THE USER'S TERMINAL.
- * WHEN TTOTRAP PROCESSES THE "FORCE" FUNCTION, IT TRANSMITS
- * THE BUFFER CONTENT TO IAF AND PROCEEDS TO SWAP THE TASK
- * WITHOUT ANY USAGE OF THE SPINWHEELS FUNCTION.
- *
- * WHEN TTOTRAP DECIDES TO SWAPOUT, IT MUST CALL PAUSEIO IN
- * THE WORKFILE MANAGER. THIS IS BECAUSE WORKIO DEALS WITH
- * SOME TRANSIENT RESOURCE, SUCH AS ITS CIRCULAR BUFFER, AND
- * NEEDS THE OPPORTUNITY TO COMPLETE ITS USAGE OF SUCH
- * RESOURCES.
- *
- * ENTRY TTOTYPE - FUNCTION CODE.
- * TTOADDR - ADDRESS OF TEXT.
- * TTOLEN - LENGTH OF TEXT.
- * TASKNXTTTO[CURTASK] - AMOUNT OF TEXT ALREADY QUEUED.
- * TTOBUFFER - ADDRESS OF THIS TASK'S BUFFER.
- * ALL SPINWHEELS PARAMETERS SETUP.
- *
- * EXIT TTOLEN - DECREMENTED.
- * TTOADDR - INCREMENETED.
- * TASKNXTTTO[CURTASK] - AMOUNT OF TEXT NOW IN BUFFER.
- * RUNTIME - INCREMENTED IF SWAPOUT.
- * ACCTOUT - INCREMENTED.
- *
- * CALLS MIN, MOVEWD, MELT, INSTRMNT1, TRANSMIT,
- * SPINWHEELS, CLEARQUE, PAUSEIO, ENDTRANS.
- *
- * USES TTOQUIT, TASKTYPTTO[CURTASK].
- #
- ITEM TMP1 I; # TEMPORARY STORAGE #
- ITEM TMP2 I; # TEMPORARY STORAGE #
- ITEM ENDBLOCK I=O"0014 0000 0000 0000 0000"; # BLOCK TERMINATOR #
- TRCSTR("NTR OTRP$");
- IF NOT CURUSOKOUT THEN IORET # FIRST TRANS ONLY #
- P<MOVFROM>=TTOADDR;
- ACCTOUT=ACCTOUT+TTOLEN; # ACCOUNT FOR OUTPUT #
- TTOQUIT=FALSE;
- WHYLE NOT TTOQUIT DO # SEND ALL TEXT #
- BEGIN
- TMP1=SIZTTOBUF-TASKNXTTTO[CURTASK]-1; # AVAILABLE ROOM #
- TMP2=MIN(TMP1,TTOLEN); # AMOUNT TO SEND #
- P<MOVFROM>=TTOADDR;
- P<MOVTO>=LOC(TTOBUFFER)+2+TASKNXTTTO[CURTASK];
- MOVEWD(TMP2,MOVFROM,MOVTO);
- TTOLEN=TTOLEN-TMP2;
- TTOADDR=TTOADDR+TMP2;
- TASKNXTTTO[CURTASK]=TASKNXTTTO[CURTASK]+TMP2;
- TASKTYPTTO[CURTASK]=0; # DETERMINE TRANSMIT #
- CONTROL IFGQ PARANOIA,4;
- IF TASKNXTTTO[CURTASK] GR SIZTTOBUF THEN MELT("TTOTRAP 1$");
- CONTROL FI;
- CONTROL IFEQ METERING,1;
- IF TASKNXTTTO[CURTASK] GQ SIZTTOBUF-1
- THEN INSTRMNT1(INSTST"XSTTO");
- CONTROL FI;
- IF (TTOTYPE EQ TTOST"FORCE" AND TASKNXTTTO[CURTASK] NQ 0)
- OR TASKNXTTTO[CURTASK] GQ (SIZTTOBUF-1)
- THEN TASKTYPTTO[CURTASK]=SMF2IAF"MSGOUT";
- IF TTOTYPE EQ TTOST"PROMPT" AND TTOLEN EQ 0
- THEN TASKTYPTTO[CURTASK]=SMF2IAF"PROMPT";
- IF TASKTYPTTO[CURTASK] NQ 0 THEN # TRANSMIT #
- BEGIN
- P<MOVFROM>=LOC(ENDBLOCK); # ADD 0014 CONTROL BYTE #
- P<MOVTO>=LOC(TTOBUFFER)+2+TASKNXTTTO[CURTASK];
- MOVEWD(1,MOVFROM,MOVTO);
- TASKNXTTTO[CURTASK]=TASKNXTTTO[CURTASK]+1;
- TRANSMIT; # TRANSMIT BUFFER TO IAFEX #
- TASKNXTTTO[CURTASK]=0;
- IF TTOTYPE NQ TTOST"FORCE" AND TASKTYPTTO[CURTASK]
- EQ SMF2IAF"MSGOUT" THEN # ATTEMPT CONTINUE #
- BEGIN
- SPINWHEELS; # LOOK FOR QUICK ACKNOWLEGE #
- IF TASKREQUE[CURTASK] THEN # CAN CONTINUE #
- BEGIN
- TRCSTR("KWIK TOCIN$");
- CLEARQUE; # ACKNOWLEDGE #
- TASKTYPTTO[CURTASK]=0; # AVOID SWAPOUT #
- CONTROL IFEQ METERING,1;
- INSTRMNT1(INSTST"KWIKTOC");
- CONTROL FI;
- END
- END
- END
- IF TASKTYPTTO[CURTASK] NQ 0 OR TTOTYPE NQ TTOST"NORMAL" THEN
- BEGIN
- PAUSEIO;
- RUNTIME=RUNTIME+TIMEOFDAY-TASKTIME[CURTASK];
- ENDTRANS;
- END
- IF TTOLEN LQ 0 THEN TTOQUIT=TRUE;
- END
- IOEND # OF TTOTRAP #
- PAGE # SWAPPING ROUTINE #
- PROC SWAP;
- IOBEGIN(SWAP)
- #
- ** SWAP - SWAP THIS TASK IN OR OUT.
- *
- * THE SWAP ROUTINE READS OR WRITE THE SWAP PAGE FOR THE
- * CURRENTLY EXECUTING TASK. FOR A SWAPIN, WE READ THE PAGE
- * ALREADY ASSIGNED TO THE USER. FOR A SWAPOUT, WE ASSIGN A
- * PAGE. THE FIRST PRIORITY IN PAGE SELECTION IS EXTENDED
- * MEMORY IF AVAILABLE, HEALTHY, AND NOT YET FILLED UP. THE
- * LOWER PRIORITY IS TO SELECT A DISK PAGE. DISK PAGES ARE
- * PHASED OR INTERLEAVED ROUND-ROBIN ACROSS THE SEVERAL SWAP
- * DATABASES.
- *
- * THE SWAP ROUTINE CAN RECOVER FROM A PARITY ERROR IN AN
- * EXTENDED MEMORY TRANSFER, BUT DOES NOT ATTEMPT TO HANDLE
- * DEVICE ERRORS ON DISKS. WHEN AN ERROR IS DETECTED FROM
- * EXTENDED MEMORY, A USER BEING SWAPPED IN WILL HAVE HIS TASK
- * ABORTED, WHILE A USER BEING SWAPPED IS UNHARMED. ERROR
- * RECOVERY INCLUDES THE FAULT-OUT OF THE BAD PAGE,
- * DETERMINATION WHETHER THE ENTIRE EXTENDED MEMORY FIELD
- * LENGTH SHOULD BE ABANDONED DUE TO WIDESPREAD ERRORS, AND
- * FOR SWAPOUT WE ALSO ALLOCATE ANOTHER PAGE AND TRY THE SWAP
- * AGAIN.
- *
- * WHILE SWAP IS EXECUTING, THE DISPATCHING AREA IN THE COMMON
- * BLOCK IS CONSIDERED TO BE IRRELEVANT. THEREFORE, THE
- * ROUTINE WHICH MANAGES THE BRUTE-FORCE SHUFFLING OF THE
- * COMMON BLOCK (SUBROUTINE GETCOMON) NEEDS TO KNOW WHEN
- * SWAPPING IS IN EFFECT. THIS SWAP ROUTINE IS THUS REQUIRED
- * TO TURN THE TASKSWPNOW FLAG ON AT ENTRY TIME AND TO TURN IT
- * OFF AT EXIT TIME. NO REENTRANT EVENTS CAN OCCUR BETWEEN
- * THE ACTUAL ENTRY OR EXIT AND THE SETTING OF THE TASKSWPNOW
- * FLAG.
- *
- * ENTRY TASKSWPIN[CURTASK] - DIRECTION OF SWAP.
- * TIMEOFDAY - CURRENT.
- * SWAPBITS - ALLOCATION BITMASK.
- * P<SWAPMASK> - ENABLES/DISABLES EXTENDED MEMORY PAGES.
- * CURUSSWPPAG - USERS PAGE FOR SWAPIN.
- * TASKADDR[CURTASK] - MEMORY ADDRESS FOR SWAP PAGE.
- * SWAPLEN - LENGTH OF A PAGE IN WORDS.
- * SWAPPRUS - LENGTH OF A PAGE IN SECTORS.
- * ECSERRORS - PREVIOUS EXTENDED MEMORY ERRORS.
- * SWPFETDONE[ALL] - INTERLOCKS ON DISK FILES.
- * SWPFET[ALL] - THE DISK FET'S.
- * MAXSWPPAG - HIGHEST DISK PAGE CREATED TO DATE.
- *
- * EXIT TIMEOFDAY - CURRENT.
- * SWAPBITS - UPDATED.
- * SWAPGOOD - EXTENDED MEMORY ERRORS FAULTED HERE.
- * ECSERRORS - INCREMENTED IF ERRORS.
- * MAXSWPPAG - INCREMENTED IF HIGHWATERMARK RAISED.
- * TASKTIME[CURTASK] - TIMEOFDAY.
- * STATUSMSG - MAY CONTAIN ERROR MSG.
- * CURUSSWPPAG - PAGE SELECTED FOR SWAPOUT.
- * CURUSVICTIM - TRUE IF ECS PARITY ERROR ON SWAPIN.
- *
- * CALLS ALLOC, MELT, INSTRMNT1, READECS, WRITECS,
- * FORCEALLOC, SMFDLY, MAKEFET, READ, WRITER, REWRITR,
- * SMFRCL, INSTRMNT2.
- *
- * USES TASKSWPNOW[CURTASK], TASKSWPFIL[CURTASK],
- * TASKSWPPRU[CURTASK], P<MOVFROM>, P<MOVTO>, SWPFET.
- #
- ITEM TMP1,TMP2;
- # SWAP IS REQUIRED TO SET TASKSWPNOW BEFORE ANY DELAYS OCCUR #
- TRCSTR("NTR SWP$");
- TASKSWPNOW[CURTASK]=TRUE;
- TASKTIME[CURTASK]=TIMEOFDAY;
- SWAPSTART:
- IF NOT TASKSWPIN[CURTASK] THEN # ALLOC PAGE #
- BEGIN
- ALLOC(SWAPBITS,SWAPMASK,TMP1,NUMSWPBIT);
- IF TMP1 EQ 0 THEN MELT("SWPO 2$");
- CURUSSWPPAG=TMP1; # SAVE INVIOLATE #
- END
- TRCBOTH("PAGE$",CURUSSWPPAG);
- IF CURUSSWPPAG LQ NUMSWPECS THEN # ECS SWAP #
- BEGIN
- TRCSTR("SWPECS$");
- CONTROL IFEQ ECSCODE,0;
- CONTROL IFGQ PARANOIA,1;
- MELT("SWP 3$");
- CONTROL FI;
- CONTROL FI;
- CONTROL IFEQ ECSCODE,1;
- CONTROL IFEQ METERING,1;
- INSTRMNT1(INSTST"SWPE");
- CONTROL FI;
- P<MOVFROM>=TASKADDR[CURTASK];
- P<MOVTO>=(CURUSSWPPAG-1)*SWAPLEN;
- IF TASKSWPIN[CURTASK] THEN READECS(SWAPLEN,MOVTO,MOVFROM,TMP1);
- ELSE WRITECS(SWAPLEN,MOVFROM,MOVTO,TMP1);
- CONTROL IFGQ ECSERRMAX,0;
- IF TMP1 NQ 0 THEN # ECS ERROR, RETRY OR KILL #
- BEGIN
- ECSERRORS=ECSERRORS+TMP1;
- IF ECSERRORS GQ ECSERRMAX THEN
- BEGIN
- ECSDOWN=TRUE;
- C<22,6>STATUSMSG="EM OFF";
- END
- # FAULT OUT THIS PAGE TO PROTECT FUTURE USERS #
- FORCEALLOC(SWAPGOOD,CURUSSWPPAG,NUMSWPBIT);
- IF TMP1 GQ 3 AND TASKSWPIN[CURTASK] THEN CURUSVICTIM=TRUE;
- IF NOT TASKSWPIN[CURTASK] THEN GOTO SWAPSTART;
- END
- CONTROL FI;
- CONTROL IFLS ECSERRMAX,0;
- IF TMP1 NQ 0 THEN MELT("ECS HARDWARE$");
- CONTROL FI;
- CONTROL FI;
- END
- ELSE # DISK SWAPPING #
- BEGIN
- TASKSWPFIL[CURTASK]=1+MOD(CURUSSWPPAG-1-NUMSWPECS,NUMSWPFET);
- TASKSWPPRU[CURTASK]=1+(CURUSSWPPAG-1-NUMSWPECS)/NUMSWPFET*SWAPPRUS;
- TRCBOTH("SWPDSK$",TASKSWPFIL[CURTASK]);
- TRCDEC(TASKSWPPRU[CURTASK]);
- CONTROL IFEQ METERING,1;
- INSTRMNT1(INSTST"SWPD");
- CONTROL FI;
- WHYLE NOT SWPFETDONE[TASKSWPFIL[CURTASK]] DO SMFDLY;
- TMP1=TASKSWPFIL[CURTASK]; # VALID TILL SMFRCL #
- C<0,6>TMP2="SMFSWP";
- C<6,1>TMP2=O"33"+TMP1-1;
- P<ANYFET>=LOC(SWPFET[TMP1]);
- P<MOVFROM>=TASKADDR[CURTASK];
- MAKEFET(ANYFET,TMP2,MOVFROM,SWAPBUFLEN);
- SWPFETR[TMP1]=TRUE;
- SWPFETRR[TMP1]=TASKSWPPRU[CURTASK];
- IF TASKSWPIN[CURTASK] THEN READ(ANYFET,0);
- ELSE
- BEGIN
- SWPFETIN[TMP1]=SWPFETIN[TMP1]+SWAPLEN;
- IF CURUSSWPPAG GR MAXSWPPAG THEN
- BEGIN
- MAXSWPPAG=CURUSSWPPAG;
- SWPFETRR[TMP1]=LOC(DUMB);
- WRITER(ANYFET,0);
- END
- ELSE REWRITR(ANYFET,0);
- END
- SMFRCL(ANYFET);
- END
- # ONCE TASKSWPNOW IS CLEARED, SWAP CANNOT DELAY ANYMORE #
- TASKSWPNOW[CURTASK]=FALSE;
- CONTROL IFEQ METERING,1;
- TMP1=TIMEOFDAY-TASKTIME[CURTASK];
- INSTRMNT2(INSTST"SWPTIM",TMP1);
- CONTROL FI;
- TASKTIME[CURTASK]=TIMEOFDAY;
- IOEND # OF SWAP #
- PAGE # USER/SYSTEM-STATE CHANGING CODE #
- PROC PAUSE;
- IOBEGIN(PAUSE)
- #
- ** PAUSE - INTERFACE TO EXECUTIVE TO START/END TIME SLICE.
- *
- * PAUSE IS THE ROUTINE USED BY USER-MODE ROUTINES TO END A
- * SLICE ON THE CPU, AND BY THE EXECUTIVE TO RESUME EXECUTION
- * WHERE THE PREVIOUS TIME SLICE ENDED. THUS, PAUSE EXITS TO
- * LABEL AFTERSLICE AND PROVIDES THE LABEL RESUME, WHICH
- * RUNJOBS WILL JUMP TO JUST IN FRONT OF THE DEFINITION OF THE
- * AFTERSLICE LABEL.
- #
- XDEF LABEL RESUME;
- XREF LABEL AFTERSLICE;
- GOTO AFTERSLICE;
- RESUME: # HERE FOR NEW TIMESLICE #
- IOEND # OF PAUSE #
- PROC TRANSACT;
- BEGIN
- #
- ** TRANSACT - TRANSITION FROM EXECUTIVE TO USER FOR SWAPIN.
- *
- * TRANSACT IS USED BY THE RUNJOBS EXECUTIVE, JUST BEFORE
- * RUNJOBS DEFINES THE AFTERTRANS LABEL, TO SWITCH FROM
- * EXECUTIVE MODE TO USER MODE AND PERFORM SWAPINS. TRANSACT
- * THEN REPAIRS THE COMMON BLOCK DISPATCHING AREA, REPAIRS THE
- * RETURN JUMP WORDS IN ALL ACTIVE SUBROUTINE ENTRY POINTS,
- * CHECKS FOR CERTAIN INTERRUPT CONDITIONS, AND EXITS VIA A
- * JUMP TO THE MORETRANS LABEL IN THE ENDTRANS ROUTINE. THIS
- * TYPE OF EXIT IS USED BECAUSE THE TASK IS PRESUMED TO HAVE
- * HAVE COMPLETED ITS PREVIOUS SWAPPED-IN TRANSACTION BY
- * CALLING ENDTRANS, AND ENDTRANS IS RESUMED TO HAVE JUMPED TO
- * THE EXECUTIVE JUST IN FRONT OF THE DEFINITION OF LABEL
- * MORETRANS.
- *
- * ENTRY MAY BE CALLED ONLY BY RUNJOBS TRANSACTION SECTION.
- * CURUSINTRPT - AN INTERRUPT MUST BE COMMUNICATED TO
- * USER-MODE CODE AFTER SWAPIN IS COMPLETE.
- * SHUTDOWN - CAUSES SYNTHESIS OF INTERRUPTS.
- * CURUSRCVRY - FSE JOB DETACHING.
- * RSTKPTR - SIZE OF REENTRANCY STACK.
- *
- * EXIT VIA LABEL MORETRANS.
- * RENTSTK - REENTRANCY STACK.
- * COMMON BLOCK AND SUBROUTINE ENTRIES REBUILT.
- * USRBRK - 1 IF ANY INTERRUPT PASSED TO USER.
- * CURUSVICTIM - TRUE IF SWAPIN RUINED USER DATA.
- * FORCESINGLE, FORCENULL - ADDITIONAL INTERRUPTS.
- * WORKFILE CHECKPOINTED AND EXIT VIA LABEL AFTEREDIT
- * IF CURUSRCVRY IS ON.
- *
- * CALLS SWAP, DEALLOC, GETCOMMON, CHECKIO, MOVEWD, SPREAD.
- *
- * USES SWAPRSTK, TASKSWPIN[CURTASK].
- #
- XREF LABEL AFTEREDIT;
- XREF LABEL AFTERTRANS;
- XREF LABEL MORETRANS;
- TRCSTR("NTR TRNSCT$");
- TASKSWPIN[CURTASK]=TRUE;
- SWAP;
- # ONCE SWAP RETURNS, WE CANNOT REENTER UNTIL AFTER GETCOMMON #
- IF SHUTDOWN NQ 2 THEN DEALLOC(SWAPBITS,CURUSSWPPAG,NUMSWPBIT);
- CURUSSWPPAG=0;
- LASTTASK=0; # RECONSTRUCT COMMON AFTER SWAP #
- GETCOMMON;
- # END OF TIME-CRITICAL SEQUENCE #
- IF CURUSINTRPT THEN USRBRK=1;
- IF CURUSVICTIM THEN
- BEGIN
- SMFVICTIM=TRUE;
- ERRSTRING="ECS HARDWARE$";
- END
- IF SHUTDOWN NQ 0 THEN FORCESINGLE=TRUE;
- IF SHUTDOWN GR 1 THEN
- BEGIN
- CURUSINTRPT=TRUE;
- USRBRK=1;
- FORCENULL=TRUE;
- END
- IF CURUSRCVRY THEN # CHKPT AND END EDIT #
- BEGIN
- FORCENULL=TRUE;
- IF SHUTDOWN EQ 2 THEN
- BEGIN
- USRBRK=0;
- CURUSINTRPT=FALSE;
- END
- IF NOT CURUSDONE THEN
- BEGIN # IF WORKFILE NOT YET CHECKPOINTED #
- CHECKIO; # CHECKPOINT WORKFILE #
- END
- GOTO AFTEREDIT;
- END
- MOVEWD(RSTKPTR-1,SWAPRSTK,RENTSTK);
- SPREAD(RSTKPTR,RENTSTK);
- # OUR RETURN GOES NOT TO CALLER BUT TO USER #
- GOTO MORETRANS; # LET GATHERED CODE RETURN TO USER #
- END # OF TRANSACT #
- PROC ENDTRANS;
- IOBEGIN(ENDTRANS)
- #
- ** ENDTRANS - END A TRANSACTION WITH SWAPOUT.
- *
- * ENDTRANS IS CALLED ONLY BY TTOTRAP, FOR THE PURPOSE OF
- * SWAPPING THE CURRENT TASK OUT. ENDTRANS CONSOLIDATES DATA
- * FROM SUBROUTINE ENTRY POINTS AND FROM THE DISPATCHABLE
- * COMMON BLOCK, THEN SWAPS THE MEMORY IMAGE OUT. ENDTRANS
- * THEN EXITS BY JUMPING TO LABEL AFTERTRANS IN THE RUNJOBS
- * EXECUTIVE. ENDTRANS PROVIDES THE DEFINITION OF LABEL
- * MORETRANS SO THAT WHEN RUNJOBS CALLS TRANSACT TO SWAP THIS
- * USER BACK IN, TRANSACT CAN JUMP TO THE ADDRESS AT WHICH THE
- * TASK HAD FORFEITED CONTROL.
- *
- * ENDTRANS IS ALLOWED TO BE CALLED ONLY BY TTOTRAP BECAUSE
- * THE TASK CANNOT SWAPOUT WITH ANY RESIDUAL OUTPUT LEFT IN
- * THE BUFFER OWNED BY THE TASK.
- *
- * ENTRY ONLY FROM TTOTRAP.
- * RSTKPTR - DEPTH OF REENTRANCY STACK.
- * RENTSTK - THE REENTRANCY STACK.
- *
- * EXIT VIA LABEL AFTERTRANS.
- *
- * CALLS GATHER, MOVEWD, PUTCOMMON, SWAP, MELT.
- *
- * USES SWAPRSTK, TASKSWPIN[CURTASK].
- #
- XREF LABEL AFTERTRANS;
- XDEF LABEL MORETRANS;
- TRCSTR("NTR NDTRNS$");
- GATHER(RSTKPTR,RENTSTK);
- MOVEWD(RSTKPTR-1,RENTSTK,SWAPRSTK);
- # MUST EXECUTE INSTANTLY FROM PUTCOMMON INTO START OF SWAP #
- PUTCOMMON; # MAKE COMMON SWAPPABLE #
- TASKSWPIN[CURTASK]=FALSE;
- SWAP;
- # END OF TIME-CRITICAL SEQUENCE #
- CONTROL IFGQ PARANOIA,3;
- IF TASKNXTTTO[CURTASK] NQ 0 THEN MELT("NTRNS 2$");
- CONTROL FI;
- GOTO AFTERTRANS;
- # RETURN GOES BACK TO USER #
- MORETRANS:
- IOEND # OF ENDTRANS #
- PAGE # INITIALIZATION AND TERMINATION #
- PROC INITMON;
- BEGIN
- #
- ** INITMON - INITIALIZE SMFEX.
- *
- * INITMON IS THE PRESET ROUTINE FOR SMFEX. THE FOLLOWING
- * FUNCTIONS ARE PERFORMED --
- *
- * THE PARAMETERS CRACKED BY THE OPERATING SYSTEM AT RA+2 ARE
- * CHECKED FOR RECOVERY MODE OR FOR A NUMBER OF TASKS TO BE
- * FORMATTED. THE SHUTDOWN FLAG IS SET FOR RECOVERY MODE, AND
- * THE TASKSAVAIL FLAG IS SET AND FORCED WITHIN REASONABLE
- * BOUNDS FOR A NUMERIC PARAMETER.
- *
- * MISCELLANEOUS POINTERS AND LENGTH FIELDS ARE COMPUTED. THE
- * FIELD LENGTH IS THEN INCREASED TO MAKE ROOM FOR THE MODEL
- * FORMAT OF THE COMMON BLOCK. THE FIELD LENGTH IS INCREASED
- * TO ALLOCATE THE TERMINAL INPUT BUFFERS. THE BITMAPS USED
- * FOR ALLOCATION OF SMFEX RESOURCES ARE INITIALIZED. THEN
- * EACH TASK IS BUILT OUT OF INCREASED FIELD LENGTH.
- *
- * TASK CONSTRUCTION IS DELEGATED TO THE BUILDTASK ROUTINE.
- * THE COMMON BLOCK IS USED TO CONSTRUCT THIS TASK'S POINTERS
- * FOR A NUMBER OF PER-TASK ARRAYS. THEN COMMON BLOCK IS THEN
- * COPIED INTO THE EXTENDED FIELD LENGTH SO EACH TASK CAN
- * CONTAIN ITS OWN BASE ADDRESSES FOR ARRAYS.
- *
- * THE EXTENDED MEMORY FIELD LENGTH IS DETERMINED BY SEEING
- * HOW MUCH MEMORY IS DESIRED FOR THE COMPILE-TIME
- * CONFIGURATION AND HOW MUCH IS ACTUALLY AVAILABLE FROM THE
- * RUNNING SYSTEM. THE ALLOCATION BITMAPS ARE MODIFIED IF
- * NEEDED TO ALLOW FOR THE NUMBER OF ECS SWAP PAGES ACTUALLY
- * OBTAINED. EXTENDED MEMORY SWAPPING IS COMPLETELY DISABLED
- * IF THE RUNNING SYSTEM CANNOT PROVIDE ANY SECONDARY FIELD
- * LENGTH AT ALL.
- *
- * FOR SUBSYSTEM RECOVERY, A SHORTENED INITMON ALGORITHM TAKES
- * EFFECT. WE ASSUME THE PREVIOUS SMFEX JOB STEP EXECUTED AN
- * IDENTICAL VERSION OF THIS PROGRAM (I.E., SMFEX HAS NOT BEEN
- * SYSEDITED WHILE RUNNING) AND THAT THE TERMINATION OF THE
- * PREVIOUS SMFEX JOB STEP EXITED INTO A "DMB" FORMAT DUMP
- * FILE. THE DUMP FILE IS SCANNED TO OBTAIN THE USER TABLE.
- * WE CHECK ALL USER TABLE ENTRIES FOR RECOVERABLE TASKS AND
- * QUEUE THOSE USERS FOR SWAPIN. RECOVERABLE TASKS ARE THOSE
- * WHICH EXIST ON A SWAP PAGE BUT NOT IN MEMORY. FOR
- * SUBSYSTEM RECOVERY, THE INITMON ALGORITHM TERMINATES AT
- * THIS POINT IN THE FLOW.
- *
- * FOR TRUE SUBSYSTEM INITIATION, THE REMAINDER OF THE INITMON
- * ALGORITHM IS AS FOLLOWS --
- *
- * ALL DISK SWAP FILES ARE EVICTED.
- *
- * THE NEGATIVE FIELD LENGTH IS BOOSTED TO ITS ANTICIPATED
- * HIGH WATER MARK BY ALLOCATING THEN RETURNING A LARGE GROUP
- * OF TOKEN FILES. THIS IS DONE BECAUSE THE TLX PP ROUTINE
- * WHICH TRANSITIONS USERS FROM SINGLE USER MODE TO MULTI USER
- * MODE IS UNABLE TO INCREASE OUR NEGATIVE FIELD LENGTH TO
- * MAKE ROOM FOR LOCAL FNT'S FOR THE TRANSFERRED WORKFILES.
- * TLX TREATS OUR PRE-ALLOCATED NEGATIVE FIELD LENGTH AS A
- * LIMITATION AS TO WHETHER A PARTICULAR SINGLE USER EDITOR
- * JOB WILL BE ACCEPTED INTO MULTI USER MODE.
- *
- * FINALLY, COMMUNICATIONS ARE ESTABLISHED WITH IAFEX VIA THE
- * SCP/UCP FACILITY. SMFEX IS THE UCP AND IAFEX IS THE SCP.
- #
- ITEM TMP1,TMP2,TMP3,TMP4;
- P<CORE>=0;
- IF B<00,01>MEM[CSMR] EQ 0 THEN # IF SYSTEM CHARACTER SET = 63 #
- BEGIN
- XLTINTXP[O"00"]=O"4045"; # COLON = PERCENT #
- XLTINTXP[O"63"]=O"4072"; # PERCENT = COLON #
- XLTDSPXP[O"00"]=O"4045"; # COLON = PERCENT #
- XLTDSPXP[O"63"]=O"4072"; # PERCENT = COLON #
- XLTDSPINT[O"00"]=O"0063"; # COLON = PERCENT #
- XLTDSPINT[O"63"]=O"0000"; # PERCENT = COLON #
- XLTXPINT[O"45"]=O"0000"; # PERCENT = COLON #
- XLTXPINT[O"72"]=O"0063"; # COLON = PERCENT #
- XLTINTDSP[O"00"]=O"0055"; # COLON = BLANK #
- END
- SFMCSTF;
- IF C<0,7>MEM[2] EQ "RECOVER" THEN SHUTDOWN=2;
- ELSE
- BEGIN
- TMP1=0;
- TMP2=0;
- TMP3=C<0,1>MEM[2]-O"33";
- WHYLE TMP2 LQ 6 AND TMP3 GQ 0 AND TMP3 LQ 9 DO
- BEGIN
- TMP1=TMP1*10+TMP3;
- TMP2=TMP2+1;
- TMP3=C<TMP2,1>MEM[2]-O"33";
- END
- IF TMP1 GQ 2 AND TMP1 LQ NUMTASKS THEN TASKSAVAIL=TMP1;
- END
- P<SWAPMASK>=LOC(SWAPGOOD);
- SWAPLEN=LOC(SWAPEND)-LOC(DATASTART);
- DISPATLEN=LOC(DISPATEND)-LOC(DATASTART);
- FIELDLEN=B<42,18>MEM[O"65"];
- MODELPTR=FIELDLEN;
- MODELLEN=LOC(SWAPEND)-LOC(DATAEND);
- FIELDLEN=MODELPTR+MODELLEN;
- FLDLEN(FIELDLEN+4);
- P<MOVTO>=MODELPTR;
- MOVEWD(MODELLEN,DATAEND,MOVTO);
- FOR TMP3=1 STEP 1 UNTIL NUMTTIBUF DO
- BEGIN
- TTIBUFADDR[TMP3]=FIELDLEN;
- FIELDLEN=FIELDLEN+SIZTTIBUF;
- FLDLEN(FIELDLEN+4);
- END
- FOR TMP1=1 STEP 1 UNTIL MAXREENT DO RSTK[TMP1]=LOC(RSTK[TMP1]);
- INITBITMAP(SWAPBITS,NUMSWPBIT,NUMSWPECS+NUMSWPDSK);
- INITBITMAP(TTIBITS,NUMTTIBIT,NUMTTIBUF);
- INITBITMAP(SWAPGOOD,NUMSWPBIT,NUMSWPECS+NUMSWPDSK);
- INITBITMAP(SWAPBAD,NUMSWPBIT,NUMSWPECS+NUMSWPDSK);
- INITBITMAP(TTIGOOD,NUMTTIBIT,NUMTTIBUF);
- KILLECSBITS(SWAPBAD);
- MEM[USRBASE]=LOC(USERTAB); # FOR EASY C DISPLAY #
- MEM[SLTBASE]=LOC(TASKTAB);
- CONTROL IFEQ METERING,1;
- MEM[STTBASE]=LOC(INSTDATA);
- CONTROL FI;
- FOR CURTASK=1 STEP 1 UNTIL TASKSAVAIL DO BUILDTASK(CURTASK);
- SWAPLEN=SWAPLEN+TASKDSPADR[1]-TASKADDR[1];
- SWAPPRUS=((SWAPLEN+O"100")/O"100");
- SWAPBUFLEN=1+SWAPPRUS*O"100";
- FLDLEN(FIELDLEN+4);
- CONTROL IFEQ ECSCODE,1;
- # REQUEST ECS FIELD LENGTH/ SEE IF IT IS THERE #
- GETFLCE(ECSFIELD); # GET VALIDATION LIMIT #
- TESTECS(TMP1); # GET EXISTENCE/ENABLED #
- IF B<0,12>ECSFIELD NQ 0 AND TMP1 NQ 0 THEN
- BEGIN
- # ALLOCATE DESIRED OR AVAILABLE ECS FIELD LENGTH #
- ECSFIELD=MIN(NUMSWPECS*SWAPLEN,512*B<0,12>ECSFIELD);
- FLDLENE(ECSFIELD);
- SETRFLE((ECSFIELD+511)/512);
- PROTEON; # SINCE ABORT RECOVERY ADVANCES #
- # TURN OFF ANY SWAP PAGES BEYOND AVAILABLE FIELD LENGTH #
- TMP1=ECSFIELD/SWAPLEN;
- FOR TMP2=TMP1+1 STEP 1 UNTIL NUMSWPECS
- DO FORCEALLOC(SWAPGOOD,TMP2,NUMSWPBIT);
- END
- ELSE KILLECSBITS(SWAPGOOD); # TURN OFF ALL ECS SWAP PAGES #
- CONTROL FI;
- CONTROL IFEQ ECSCODE,0;
- KILLECSBITS(SWAPGOOD);
- CONTROL FI;
- IF SHUTDOWN EQ 2 THEN
- BEGIN
- TERMMON; # SHUT OFF ANY INPUT #
- P<MOVFROM>=FIELDLEN;
- MAKEFET(DMBFET,"ZZZZDMB",MOVFROM,O"1001");
- FIELDLEN=FIELDLEN+O"1001";
- FLDLEN(FIELDLEN+4);
- REWIND(DMBFET,1);
- READ(DMBFET,0);
- TMP1=0;
- TMP4=0;
- FOR TMP2=0 STEP 1 UNTIL O"61" DO
- BEGIN # UNTIL RIGHT (CM) CONTROL WORD #
- READO(DMBFET,TMP1,TMP4); # ACCESS NEXT CONTROL WORD #
- IF TMP4 NQ 0 THEN MELT("RCVR 1$");
- END
- IF C<0,2>TMP1 NQ "CM" THEN MELT("RCVR 2$");
- FOR TMP2=1 STEP 1 UNTIL LOC(USERTAB) DO
- BEGIN # CONSUME LOWER FIELD LENGTH #
- READO(DMBFET,TMP1,TMP4);
- IF TMP4 NQ 0 THEN MELT("RCVR 3$");
- END
- # FINALLY READ IN THE USER TABLE #
- FOR TMP2=1 STEP 1 UNTIL 3*NUMSMFUSR DO
- BEGIN
- P<MOVTO>=LOC(USERTAB)+TMP2-1;
- READO(DMBFET,MOVTO,TMP4);
- IF TMP4 NQ 0 THEN MELT("RCVR 4$");
- END
- REWIND(DMBFET,1); # IN CASE TAKE ANOTHER DUMP #
- FOR CURUSER=1 STEP 1 UNTIL NUMSMFUSR DO
- BEGIN # UPDATE AND QUEUE CHECKPT #
- GETUSER;
- IF CURUSINTASK THEN CURUSDONE=TRUE;
- CURUSINQUE=FALSE;
- CURUSTTIBUF=0;
- CURUSQUELNK=0;
- CURUSINTASK=FALSE;
- IF CURUSLOGGED AND CURUSSWPPAG NQ 0 AND NOT CURUSDONE THEN
- BEGIN
- TRCBOTH("RECOVER$",CURUSER);
- CURUSRCVRY=TRUE;
- CURUSINTRPT=TRUE;
- PUTINQ;
- END
- PUTUSER;
- END
- FOR TMP1=1 STEP 1 UNTIL NUMSWPFET DO SWPFETDONE[TMP1]=TRUE;
- TRCSTR("END INITMON RCVR$");
- RETURN; # SO THAT NOTHING ELSE IS DONE #
- END
- FOR TMP1=1 STEP 1 UNTIL NUMSWPFET DO
- BEGIN
- CONTROL IFGR NUMSWPFET,8; BADSTUFF; CONTROL FI; # CODE DEPENDENT #
- C<0,6>TMP2="SMFSWP";
- C<6,1>TMP2=TMP1+O"32";
- P<ANYFET>=LOC(SWPFET[TMP1]);
- P<MOVFROM>=TASKADDR[1];
- MAKEFET(ANYFET,TMP2,MOVFROM,SWAPBUFLEN);
- READ(ANYFET,1); # ASSURE FNT ALLOCATE #
- EVICT(ANYFET,1); # ASSURE NO OLD DATA #
- END
- PROC GENNULL;
- BEGIN
- C<0,2>TMP2="NE";
- TMP3=TMP1;
- FOR TMP4=6 STEP -1 UNTIL 2 DO
- BEGIN
- C<TMP4,1>TMP2=O"33"+MOD(TMP3,10);
- TMP3=TMP3/10;
- END
- MAKEFET(NULLFET,TMP2,CORE,O"101");
- END # OF GENNULL #
- FOR TMP1=1 STEP 1 UNTIL NUMSMFUSR DO
- BEGIN # MANY NULL FILES TO ENLARGEN NFL #
- GENNULL;
- READ(NULLFET,1); # ASSURE FNT ALLOCATE #
- END
- FOR TMP1=1 STEP 1 UNTIL NUMSMFUSR DO
- BEGIN # THEN RELEASE THE FNT SPACE #
- GENNULL;
- RETERN(NULLFET,1);
- END
- IAFPTR=LOC(SSCINP[0]);
- INITSSCWORD[1]=IAFHEADER;
- P<SSCBUFFER>=LOC(INITSSC);
- SSCSTATUS=-1;
- # DELAY UNTIL IAF HANDSHAKE WORKS OR IDLE COMMAND DETECTED #
- WHYLE SSCSTATUS LAN O"7776" NQ 0 AND MEM[0] LAN O"100000" EQ 0 DO
- BEGIN
- SSCWORD=O"0000 0000 0000 0103 0000";
- SYSREQ("SSC",0,LOC(SSCBUFFER),IAFSSID);
- RECALL(0);
- END
- SFMSSTF;
- TRCSTR("END INITMON$");
- END # OF INITMON #
- PROC TERMMON;
- BEGIN
- #
- ** TERMMON - TERMINATE SMFEX NORMALLY.
- *
- * CALLS SFMCSTF.
- #
- SFMCSTF;
- TRCSTR("COMPLETE$");
- TRCFRC;
- END # OF TERMMON #
- PROC MELT(STR);
- BEGIN
- #
- ** MELT - TERMINATE SMFEX ABNORMALLY.
- *
- * ENTRY STR - ERROR MESSAGE FOR INTERNAL ABORT CONDITION.
- * COMPLETE - IF ALREADY SET, THEN MELT FUNCTIONS AS
- * AN INTERFACE TO PRODUCE A DAYFILE MESSAGE THEN
- * ALLOW NORMAL TERMINATION. NORMALLY, COMPLETE
- * IS FALSE AND MELT ABORTS THE JOB STEP.
- *
- * EXIT VIA LABELS ABORT OR ENDRUN.
- *
- * CALLS MESSAGE, TERMMON.
- #
- ITEM STR C(30);
- ITEM STR2 C(30);
- ITEM TMP1,TMP2;
- TRCSTR(STR);
- TRCFRC;
- STR2=STR;
- TMP2=0;
- FOR TMP1=0 STEP 1 UNTIL 29 DO
- BEGIN
- IF TMP2 EQ 0 AND C<TMP1,1>STR2 EQ "$" THEN TMP2=TMP1+1;
- END
- FOR TMP1=29 STEP -1 UNTIL TMP2 DO C<TMP1,1>STR2=0;
- MESSAGE(STR2,0,1);
- TERMMON;
- IF COMPLETE THEN ENDRUN;
- ELSE ABORT;
- END # OF MELT #
- PAGE
- #
- ** SMFEX - MAIN ALGORITHM.
- *
- * THE SMFEX MAIN ALGORITHM INITIALIZES THE SUBSYSTEM, THEN
- * LOOPS ON THE THREE MAIN PROCESSES UNTIL A COMPLETION FLAG
- * IS DETECTED. THE SUBSYSTEM IS THEN TERMINATED.
- *
- * THE THREE PROCESSING PHASES PERFORM TIME-DEPENDENT FUNCTIONS,
- * RECEIVE AND QUEUE MESSAGES FROM IAFEX, AND EXECUTE TASKS AND
- * REPLY TO IAFEX.
- *
- * CALLS INITMON, DOTIMER, DOINPUT, RUNJOBS, INITMON.
- #
- ITEM TMP1;
- INITMON; # GET EVERYTHING SET UP #
- WHYLE NOT COMPLETE DO # MAIN LOOP #
- BEGIN
- DOTIMER; # RECALL CPU, HANDLE TIMER AND OPERATOR #
- DOINPUT; # PROCESS INPUT FROM IAFEX #
- RUNJOBS; # EXECUTE ANY TASKS THAT CAN #
- END # OF MAIN LOOP #
- TERMMON; # CLOSE UP SHOP #
- ENDRUN;
- END TERM
cdc/nos2.source/opl871/smfex.txt ยท Last modified: 2023/08/05 17:24 by Site Administrator