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
  1. PRGM SMFEX;
  2. BEGIN
  3. #
  4. ** SMFEX - SCREEN MANAGEMENT FACILITY EXECUTIVE.
  5. *
  6. * COPYRIGHT CONTROL DATA SYSTEMS INC. 1992.
  7. *
  8. * THE SMFEX PROGRAM IS THE EXECUTIVE OR MONITOR FOR THE SMFEX
  9. * SUBSYSTEM. THE FUNCTION PROVIDED BY THE SMFEX SUBSYSTEM IS
  10. * AN ALTERNATE IMPLEMENTATION OF THE FULL SCREEN EDITOR (FSE)
  11. * TO BE MEMORY RESIDENT, SERVICING LARGE USER COMMUNITIES
  12. * WITH A REDUCTION IN SYSTEM SCHEDULING OVERHEAD COMPARED TO
  13. * THE CONVENTIONAL EXECUTION OF A UNIQUE JOB FOR EACH USER.
  14. *
  15. * THE SMFEX PROGRAM IS RESPONSIBLE TO MANAGE THE
  16. * MULTI-TASKING TECHNIQUE WHICH ALLOWS THE EDITOR CODE TO BE
  17. * SHARED BY MULTIPLE USERS. THE EDITOR CODE RESIDES IN
  18. * SEVERAL SOURCE MODULES OUTSIDE OF THIS PROGRAM. SMFEX AND
  19. * THE EDITING MODULES ARE COMBINED BY THE LOADER. EDITING
  20. * MODULES REQUIRE SEPARATE COMPILATION WITH CERTAIN
  21. * MODIFY-TIME DEFINITIONS CHANGED TO YIELD TWO SETS OF
  22. * RELOCATABLE MODULES, ONE SUITABLE FOR LOADER PROCESSING TO
  23. * YIELD FSE AND THE OTHER SUITABLE FOR LOADER PROCESSING TO
  24. * YIELD SMFEX.
  25. *
  26. #
  27.  
  28. DEF LISTCON #1#;
  29.  
  30. CONTROL PRESET; # UNIVERSAL DEFINITIONS #
  31.  
  32.  
  33. *CALL COMFMLT
  34. *CALL COMFFSE
  35.  
  36. # SMFEX'S OWN DEFS #
  37.  
  38. *CALL COMFSMF
  39.  
  40. # SIC CODES. IAFEX TALKS TO OUR BUFFER 0, SINGLE-USER FSE TALKS #
  41. # TO OUR BUFFER 1 WITH A DIFFERENT SET OF CODES. #
  42.  
  43. STATUS IAF2SMF
  44. INIT,
  45. MSGIN,
  46. OUTDONE,
  47. BREAK,
  48. HUNGUP,
  49. CONNECT;
  50.  
  51. STATUS SMF2IAF
  52. INIT,
  53. MSGOUT,
  54. PROMPT,
  55. LOGOUT;
  56.  
  57. STATUS TASKST
  58. EMPTY,
  59. DELAY,
  60. RECALLFET,
  61. START,
  62. SWAP,
  63. RUN,
  64. PRELIM;
  65.  
  66. # TYPES OF STATISTICS COLLECTED #
  67. STATUS INSTST
  68. THNK,
  69. RSPNS,
  70. NOTTI,
  71. NOTASK,
  72. SWPE,
  73. SWPD,
  74. CLOCKTICK,
  75. PREEMPT,
  76. SWPTIM,
  77. EDTCIO,
  78. SESSION,
  79. TRANS,
  80. XSTTO,
  81. BREAKS,
  82. HANGUPS,
  83. BGNEDT,
  84. ENDEDT,
  85. INPUT,
  86. XMIT,
  87. KWIKTOC,
  88. TASKUTIL,
  89. WORKIO,
  90. DROPCPU;
  91.  
  92. DEF MOD4(ZZ) #((ZZ) LAN 3)#;
  93. DEF MOD8(ZZ) #((ZZ) LAN 7)#;
  94. DEF MOD32(ZZ) #((ZZ) LAN 31)#;
  95. PAGE # EXTERNAL REF'S AND DEF'S #
  96.  
  97. XDEF
  98. BEGIN
  99. PROC SMFRCL; PROC SMFDLY;
  100. PROC CLEARINT; PROC VOLUNTEER;
  101. PROC TTITRAP; PROC TTOTRAP;
  102. PROC FATALTRAP; PROC CLEARQUE;
  103. CONTROL IFEQ METERING,1;
  104. PROC BGNMETER;
  105. PROC WIOSTAT;
  106. CONTROL FI;
  107. ARRAY RENTSTK [1:MAXREENT]; # SUBROUTINE STACK #
  108. BEGIN
  109. ITEM RSTK;
  110. END
  111. ITEM RSTKPTR;
  112. END
  113.  
  114. XREF PROC MOVEWD;
  115.  
  116. XREF
  117. BEGIN
  118. # FIRST COME COMPASS ROUTINES, FOR SPECIAL/OPTIMAL TRICKS #
  119. FUNC FINDBIT; FUNC NOSWDSZ;
  120. PROC SPREAD; PROC GATHER;
  121. PROC FLDLEN; PROC FLDLENE;
  122. PROC SFMSSTF; PROC SFMCSTF; PROC TESTECS;
  123. PROC READECS; PROC WRITECS;
  124. PROC GETUTAB; PROC SAVUTAB;
  125. # NOW COME THE STANDARD UOI SYMPLIB ROUTINES WE NEED #
  126. PROC WRITEO; PROC READO;
  127. PROC RECALL; PROC SYSREQ;
  128. PROC READ; PROC READC;
  129. PROC REWIND; PROC STATUSP;
  130. PROC WRITER; PROC REWRITR;
  131. PROC WRITEC; PROC WRITEW;
  132. PROC MESSAGE; PROC DISTCON;
  133. PROC RETERN; PROC GETFLCE;
  134. PROC ONSW; PROC RTIME;
  135. PROC SETRFLE; PROC PROTEON;
  136. PROC EVICT;
  137. PROC FILINFO; PROC REQUEST; PROC EESET;
  138. PROC ENDRUN; PROC ABORT;
  139. # NOW COME ENTRIES TO FSE EDITOR #
  140. FUNC MIN; FUNC MAX;
  141. PROC PROCESS; PROC EDTINIT; PROC MAKEFET; PROC EDTTERM;
  142. PROC PAUSEIO; PROC RESUMIO; PROC CHECKIO;
  143. PROC TTSYNC; PROC FATAL;
  144. PROC VDSYNCH;
  145. END
  146. PAGE # COMMON DATA AREAS #
  147. *CALL COMFDS1
  148. *CALL COMFVD2
  149. *CALL COMFDS2
  150. PAGE # EDITOR TABLES #
  151. # COMPILED HERE ONLY FOR CONTROL PRESET #
  152.  
  153. *CALL COMFTAB
  154. PAGE # SMFEX'S OWN DATA #
  155.  
  156.  
  157. ITEM TIMEOFDAY=0;
  158. ITEM SLICECOUNT=0;
  159. ITEM OLDTIMEDAY=0;
  160. ITEM NEWTIMEDAY=0;
  161. ITEM IDLEDOWN B=FALSE;
  162. ITEM STOPNOW B=FALSE;
  163. ITEM ACCEPTNONE B=FALSE;
  164. ITEM ECSDOWN B=FALSE;
  165. ITEM SHUTDOWN=0; # CONTROLS OPERATOR SHUTDON #
  166. ITEM COMPLETE B=FALSE; # USED TO SHUT WHOLE THING DOWN #
  167. ITEM CURUSER; # UTILITY VARIABLE #
  168. ITEM CURTASK; # CURRENT TASK REFERENCE #
  169. ITEM LASTTASK=0; # PREVIOUS TASK TO RUN #
  170. ITEM TASKSAVAIL=3; # TASKS CURRENTLY AVAILABLE/IN USE #
  171. ITEM TASKSBUSY=0; # NUMBER OF TASKS IN USE NOW #
  172. ITEM CHNGSTATUS; # CURRENT TASKS CHANGE OF STATUS #
  173. ITEM REMAINTTI=NUMTTIBUF; # HOW MANY BUFFERS AVAIL #
  174. ITEM DISPATLEN; # LENGTH OF DISPATCHED DATA SEGMENT #
  175. ITEM SWAPLEN; # LENGTH OF SWAPPED SEGMENT #
  176. ITEM SWAPPRUS; # LENGTH SWAPPED IN PRU COUNT #
  177. ITEM SWAPBUFLEN; # LENGTH SWAP CIRCULAR BUFFS #
  178. ITEM MAXSWPPAG=0; # HIGHEST (DISK ONLY) SWAP PAGE USED #
  179. ITEM MODELPTR; # POINTS TO COPY OF VIRGIN DATA #
  180. ITEM MODELLEN; # LENGTH OF VIRGIN COMMON COPY #
  181. ITEM FIELDLEN;
  182. ITEM LOGGEDIN=0;
  183. ITEM WRKFILLOCK B=FALSE;
  184. ITEM ENABLEFLAG=0;
  185. CONTROL IFEQ METERING,1;
  186. ITEM MAXLOGGED=0;
  187. ITEM STATTIME=0;
  188. CONTROL FI;
  189. CONTROL IFEQ ECSCODE,1;
  190. ITEM ECSFIELD=0;
  191. ITEM ECSERRORS=0;
  192. CONTROL FI;
  193. ITEM STATUSMSG C(30)="0000 USERS 00 TASKS";
  194. BASED ARRAY ANYFET;;
  195. BASED ARRAY MOVFROM;;
  196. BASED ARRAY MOVTO;;
  197.  
  198. ARRAY TTICONTROL [1:NUMTTIBUF];
  199. BEGIN
  200. ITEM TTICTLWORD = [NUMTTIBUF(0)];
  201. ITEM TTIBUFLEN U(0,0,12);
  202. ITEM TTIBUFLNK U(0,12,12);
  203. ITEM TTIBUFADDR U(0,42,18);
  204. END
  205.  
  206. ARRAY SWAPBITS (NUMSWPBIT);;
  207. ARRAY TTIBITS (NUMTTIBIT);;
  208. ARRAY SWAPGOOD (NUMSWPBIT);;
  209. ARRAY SWAPBAD (NUMSWPBIT);;
  210. ARRAY TTIGOOD (NUMTTIBIT);;
  211. BASED ARRAY SWAPMASK;;
  212.  
  213.  
  214. # NOTE THAT CURUSERTAB MUST MATCH USERTAB, WORD BY FIELD. #
  215. # NOTE ALSO THAT THE FORMATS OF THESE ARRAYS ARE HARDCODED #
  216. # IN THE COMPASS SUBROUTINES GETUTAB AND SAVUTAB. #
  217.  
  218. ARRAY CURUSERTAB (22);
  219. BEGIN
  220. ITEM CURUSLOGGED B(0)=[FALSE];
  221. ITEM CURUSINQUE B(1)=[FALSE];
  222. ITEM CURUSDROP B(02)=[FALSE]; # CURRENT USER DROP FLAG #
  223. ITEM CURUSDONE B(3)=[FALSE];
  224. ITEM CURUSINTASK B(4)=[FALSE];
  225. ITEM CURUSSTART B(5)=[FALSE];
  226. ITEM CURUSINTRPT B(6)=[FALSE];
  227. ITEM CURUSCRUNCH B(7)=[FALSE];
  228. ITEM CURUSLOSTDT B(8)=[FALSE];
  229. ITEM CURUSRCVRY B(9)=[FALSE];
  230. ITEM CURUSOLDSND B(10)=[FALSE];
  231. ITEM CURUSVICTIM B(11)=[FALSE];
  232. ITEM CURUSSTMWRK B(12)=[FALSE];
  233. ITEM CURUSOKOUT B(13)=[FALSE];
  234. ITEM CURUSSTKPTR (14)=[0];
  235. ITEM CURUSTASK (15)=[0];
  236. ITEM CURUSTTIBUF (16)=[0];
  237. ITEM CURUSQUELNK (17)=[0];
  238. ITEM CURUSIAFNUM (18)=[0];
  239. ITEM CURUSFNTPTR (19)=[0];
  240. ITEM CURUSSWPPAG (20)=[0];
  241. ITEM CURUSLASTIM (21)=[0];
  242. END
  243.  
  244.  
  245. # NOTE COMMENTS ABOVE ON RESTRICTIONS AGAINST REDEFINITION #
  246. # OF EITHER CURUSERTAB OR USERTAB. #
  247.  
  248. ARRAY USERTAB [1:NUMSMFUSR] S(3);
  249. BEGIN
  250. ITEM USERWORD0 (0)=[NUMSMFUSR(0)];
  251. ITEM USERWORD1 (1)=[NUMSMFUSR(0)];
  252. ITEM USERWORD2 (2)=[NUMSMFUSR(0)];
  253. ITEM USERFLAGS U(0,0,18);
  254. ITEM USERLOGGED B(0,0,1); # IS LOGGED FULLY IN #
  255. ITEM USERINQUE B(0,1,1); # ALREADY IN SWAPIN QUEUE #
  256. ITEM USERDROP B(00,02,01); # USER DROPPED PHONE CONNECT #
  257. ITEM USERDONE B(0,3,1); # EDIT HAS COMPLETED #
  258. ITEM USERINTASK B(0,4,1); # ASSIGNED TO SOME TASK #
  259. ITEM USERSTART B(0,5,1); # ONLY FOR RIGHT AFTER LOGGED #
  260. ITEM USERINTRPT B(0,6,1); # WE MUST SOON SERVICE BREAK KEY #
  261. ITEM USERCRUNCH B(0,7,1); # USER IS FILE-CRUNCHING,LOW PRIO #
  262. ITEM USERLOSTDT B(0,8,1); # USER LOST EXCESS INPUT DATA #
  263. ITEM USERRCVRY B(0,9,1); # SWAPPING IN ONLY TO CHKPT #
  264. ITEM USEROLDSND B(0,10,1); # MIDDLE OF SERIES OF SENDS #
  265. ITEM USERVICTIM B(0,11,1); # VICTIMIZED BY SMFEX ECS ERROR #
  266. ITEM USERSTMWRK B(0,12,1); # USE STIMULATION WRKFIL NAME #
  267. ITEM USEROKOUT B(0,13,1); # O.K. TO PRODUCE TTY OUTPUT #
  268. ITEM USERSTKPTR U(0,18,6); # REENTRANCY STACK LEVEL #
  269. ITEM USERTASK U(0,24,6); # WHICH TASK ARE WE IN #
  270. ITEM USERTTIBUF U(0,30,6); # WHICH INPUT BUFFER WE OWN #
  271. ITEM USERQUELNK U(0,36,12); # LINKAGE IN SWAP QUEUE #
  272. ITEM USERIAFNUM U(0,48,12); # WHICH IAFEX PORT #
  273. ITEM USERFNTPTR U(1,0,12); # TO SPEED UP CIO'S #
  274. ITEM USERSWPPAG U(1,12,12); # WHICH SWAP PAGE #
  275. ITEM USERLASTIM U(1,24,30); # LAST TIME STAMP #
  276. ITEM USERJSN C(2,0,4); # JOB SEQUENCE NUMBER #
  277. ITEM USEREJT U(2,24,12); # JOB EJT ORDINAL #
  278. END
  279.  
  280. ARRAY TASKTAB [1:NUMTASKS] P(13);
  281. BEGIN
  282. ITEM TASKSTATUS (0)=[0]; # CURRENT TASK STATUS #
  283. ITEM TASKFLAGS (1)=[0]; # ALL BITS OFF #
  284. ITEM TASKREQUE B(1,0,1); # USER NEEDS REPEATED SERVICE #
  285. ITEM TASKABORT B(1,2,1); # TASK IS ABORTING #
  286. ITEM TASKSWPNOW B(1,3,1); # CURRENTLY EXECING SWAP CODE #
  287. ITEM TASKSWPIN B(1,4,1); # DIRECTION OF SWAP IS IN #
  288. ITEM TASKUSER (2)=[0]; # WHICH USER IN THIS TASK #
  289. ITEM TASKNXTTTO (3)=[0]; # WHERE TO APPEND NEXT OUTPUT #
  290. ITEM TASKTYPTTO (4)=[0]; # TRANSMIT CODE DESIRED #
  291. ITEM TASKRCLADR (5)=[0]; # CURRENT RECALL FET #
  292. ITEM TASKADDR (6)=[0]; # ADDRESS OF TASK MEMORY #
  293. ITEM TASKSTKPTR (7)=[0]; # DISPATCHING RSTKPTR #
  294. ITEM TASKDSPADR (8)=[0]; # DISPATCH DATA START #
  295. ITEM TASKTIME (9)=[0]; # TIMEOFDAY SWAPPED IN #
  296. ITEM TASKSWPFIL (10)=[0]; # WHICH SWAP FILE IN USE #
  297. ITEM TASKSWPPRU (11)=[0]; # WHICH PRU IN THAT FILE #
  298. ITEM TASKPULSE (12)=[0]; # FAKE FET FOR CLOCK EVENTS #
  299. END
  300.  
  301. ARRAY SWAPQ (3);
  302. BEGIN
  303. ITEM SWPQHEAD I(0)=[0];
  304. ITEM SWPQTAIL I(1)=[0];
  305. ITEM SWPQSIZE I(2)=[0];
  306. END
  307.  
  308. ARRAY SSCINPUT [-1:O"100"]; ITEM SSCINP (0)=[O"102"(0)];
  309.  
  310. ARRAY IAFMSGWORD;
  311. BEGIN
  312. ITEM IAFHEADER; # WHOLE WORD #
  313. ITEM IAFFUNC U(0,0,12)=[SMF2IAF"INIT"];
  314. ITEM IAFTERM U(0,12,12)=[0];
  315. ITEM IAFPTR U(0,24,18)=[0];
  316. ITEM IAFLEN U(0,42,18)=[1];
  317. END
  318. ARRAY INITSSC [0:1]; ITEM INITSSCWORD=[0,0];
  319. BASED ARRAY SSCBUFFER;
  320. BEGIN
  321. ITEM SSCWORD;
  322. ITEM SSCCOUNT U(0,36,6);
  323. ITEM SSCTYPE U(0,46,2);
  324. ITEM SSCSTATUS U(0,48,12);
  325. END
  326.  
  327. ARRAY NULLFET(FETSIZ); ITEM NULLFETDT C(1,0,2);
  328.  
  329. ARRAY SWPFETS [1:NUMSWPFET] S(FETSIZ);
  330. BEGIN
  331. ITEM SWPFET;
  332. ITEM SWPFETDONE B(0,59,1);
  333. ITEM SWPFETDT C(1,0,2);
  334. ITEM SWPFETR B(1,12,1);
  335. ITEM SWPFETL U(1,36,6);
  336. ITEM SWPFETIN U(2,42,18);
  337. ITEM SWPFETOUT U(3,42,18);
  338. ITEM SWPFETCRI U(6,0,30);
  339. ITEM SWPFETW B(6,30,1);
  340. ITEM SWPFETRR U(6,31,29);
  341. END
  342. ARRAY DMBFET(FETSIZ);;
  343. ARRAY FILINFPARMS (5);
  344. BEGIN
  345. ITEM FILINFNAME C(0,0,7);
  346. ITEM FILINFLENC U(0,42,18)=[O"050001"];
  347. ITEM FILINFSTAT U(1,12,42);
  348. ITEM FILINFTTY B(1,43,1);
  349. ITEM FILINFRMS B(1,44,1);
  350. ITEM FILINFWRIT B(1,52,1);
  351. ITEM FILINFREAD B(1,53,1);
  352. ITEM FILINFFT U(1,54,6);
  353. END
  354. PAGE # MINOR UTILITY ROUTINES #
  355.  
  356.  
  357. PROC INITBITMAP(MAP,NUMWORD,NUMBIT);
  358. BEGIN
  359. #
  360. ** INITBITMAP - INITIALIZE A BIT MAP ARRAY.
  361. *
  362. * INITBITMAP PREPARES BITMAPS FOR USAGE. A BIT MAP CONSISTS
  363. * OF ANY NUMBER OF WORDS, EACH CONTAINING A 32-BIT MASK.
  364. * THE MASK IS POSITIONED 12 BITS RIGHT FROM THE SIGN BIT OF
  365. * THE WORD. THIS FORMAT ALLOWS SEARCHING FOR BITS WHICH ARE
  366. * STILL ON BY INSERTING A FLOATING POINT EXPONENT AND
  367. * EXECUTING THE NORMALIZE INSTRUCTION.
  368. *
  369. * ENTRY MAP - THE MAP TO INITIALIZE.
  370. * NUMWORD - HOW MANY WORDS IN THE MAP.
  371. * NUMBIT - HOW MANY TOTAL BITS IN THE MAP.
  372. *
  373. * EXIT MAP - SETUP.
  374. *
  375. * CALLS FORCEALLOC.
  376. #
  377. ARRAY MAP[0:999]; ITEM MAPWORD;
  378. ITEM NUMWORD, NUMBIT;
  379. ITEM TMP1;
  380. FOR TMP1=0 STEP 1 UNTIL NUMWORD-1 DO MAPWORD[TMP1]
  381. =O"00007777777777600000";
  382. FOR TMP1=NUMBIT+1 STEP 1 UNTIL NUMWORD*32
  383. DO FORCEALLOC(MAP,TMP1,NUMWORD);
  384. END # OF INITBITMAP #
  385.  
  386.  
  387. PROC BUILDTASK(WHICH);
  388. BEGIN
  389. #
  390. ** BUILDTASK - ALLOCATE FIELD LENGTH AND INIT POINTERS.
  391. *
  392. * BUILDTASK ALLOCATES FIELD LENGTH FOR PER-TASK ARRAYS, AND
  393. * MAPS OUT THE BASE ADDRESSES FOR THE ARRAYS. BUILDTASK THEN
  394. * COPIES THE SET OF POINTERS INTO THE TASK'S DISPATCHING AREA.
  395. *
  396. * ENTRY WHICH - TASK NUMBER.
  397. * FIELDLEN - CURRENT TOP OF FIELD LENGTH.
  398. *
  399. * EXIT FIELDLEN - INCREASED.
  400. * TASKSPADR[WHICH] - ADDRESS OF TASK DISPATCH AREA.
  401. * TASK DISPATCH AREA - SETUP.
  402. *
  403. * CALLS FLDLEN, MOVEWD.
  404. *
  405. * USES POINTER WORDS FOR FOLLOWING ARRAYS -
  406. * ARRAYEND, ARRAYSTART, AUDITSTAGE, BACKSTACK,
  407. * BACKSTORE, BFPRU, CHGSTRING1, DISK, DISPRSTK,
  408. * FET, FKEYDEFS, LINEBUF, LOCSTRING1, LOCSTRING2,
  409. * MOVTO, OBF, READLIST, ROWCONTROL, SPLITCONTROL,
  410. * SWAPRSTK, TITLE1LIN, TITLE2LIN, TTOBUFFER.
  411. *
  412. * NOTE THIS CODE AND THE ARRAY LAYOUT IN COMFDAT ARE
  413. * EXTREMELY INTERDEPENDENT.
  414. #
  415. ITEM WHICH;
  416. TASKADDR[WHICH]=FIELDLEN;
  417.  
  418. # FIRST ALLOCATE EDITOR ARRAYS, ORDER AND SIZE MATCHING COMFDAT #
  419. P<ARRAYSTART>=FIELDLEN;
  420. FIELDLEN=FIELDLEN+1;
  421. P<TABLEHEADR> = FIELDLEN;
  422. FIELDLEN = FIELDLEN + 6; # *TDU* TABLE LENGTH #
  423. P<TABLEWORDS> = FIELDLEN;
  424. FIELDLEN = FIELDLEN + O"272"; # *TDU* TABLE LENGTH #
  425. P<SPLITCONTROL>=FIELDLEN;
  426. FIELDLEN=FIELDLEN+2*SPLTCTLSIZ;
  427. P<ROWCONTROL>=FIELDLEN;
  428. FIELDLEN=FIELDLEN+2*(MAXROWS+1);
  429. P<BACKSTACK>=FIELDLEN;
  430. FIELDLEN=FIELDLEN+(BACKMAX+1);
  431. P<BACKSTORE>=FIELDLEN;
  432. FIELDLEN=FIELDLEN+(2*(TEMPIND+1));
  433. P<FKEYDEFS>=FIELDLEN;
  434. FIELDLEN=FIELDLEN+NUMFKEYS;
  435. P<AUDITSTAGE>=FIELDLEN;
  436. FIELDLEN=FIELDLEN+AUDITSIZE+1;
  437. P<LOCSTRING1>=FIELDLEN;
  438. FIELDLEN=FIELDLEN+STRWID;
  439. P<LOCSTRING2>=FIELDLEN;
  440. FIELDLEN=FIELDLEN+STRWID;
  441. P<CHGSTRING1>=FIELDLEN;
  442. FIELDLEN=FIELDLEN+STRWID;
  443. P<FKEYSTRINGS>=FIELDLEN;
  444. FIELDLEN=FIELDLEN+(2*NUMFKEYS);
  445. P<FKEYNUMB>=FIELDLEN;
  446. FIELDLEN=FIELDLEN+POSFKEYS;
  447. P<TITLE1LIN>=FIELDLEN;
  448. FIELDLEN=FIELDLEN+TTLLNLEN+1;
  449. P<TITLE2LIN>=FIELDLEN;
  450. FIELDLEN=FIELDLEN+TTLLNLEN+1;
  451. P<ARRAYEND>=FIELDLEN;
  452. FIELDLEN=FIELDLEN+1;
  453. # END OF ALLOCATED EDITOR ARRAYS #
  454.  
  455. # ALLOCATE BUFFERS AND CONTROL VECTORS #
  456. P<BFPRU>=FIELDLEN;
  457. FIELDLEN=FIELDLEN+BUFSIZE;
  458. P<SWAPRSTK>=FIELDLEN;
  459. FIELDLEN=FIELDLEN+MAXREENT;
  460. TASKDSPADR[WHICH]=FIELDLEN;
  461. FIELDLEN=FIELDLEN+DISPATLEN;
  462. P<DISPRSTK>=FIELDLEN;
  463. FIELDLEN=FIELDLEN+MAXREENT;
  464. P<TTOBUFFER>=FIELDLEN;
  465. FIELDLEN=FIELDLEN+SIZTTOBUF+2;
  466. P<FET>=FIELDLEN;
  467. FIELDLEN=FIELDLEN+FETSIZ;
  468. P<OBF>=FIELDLEN;
  469. FIELDLEN=FIELDLEN+OBFSIZE;
  470. P<DISK>=FIELDLEN;
  471. FIELDLEN=FIELDLEN+DSKSIZ;
  472. P<READLST>=FIELDLEN;
  473. FIELDLEN=FIELDLEN+LSTSIZE;
  474. FLDLEN(FIELDLEN+4);
  475. P<LINEBUF>=LOC(LIN);
  476. P<MOVTO>=TASKDSPADR[WHICH];
  477. MOVEWD(DISPATLEN,DATASTART,MOVTO);
  478. END # OF BUILDTASK #
  479.  
  480.  
  481. PROC GENWRKNAM;
  482. BEGIN
  483. #
  484. ** GENWRKNAM - GENERATE WORKFILE NAME FOR THIS USER.
  485. *
  486. * GENWRKNAM DETERMINES THE CORRECT FILENAME FOR THE WORK-
  487. * FILE FOR THE CURRENT USER. THE FILE NAME IS UNIQUE FOR
  488. * EACH USER AND IS GENERATED BY THE USER'S TLX CALL TO
  489. * CONNECT TO SMFEX, AND IS EQUAL TO "WK" PLUS JSN.
  490. *
  491. * ENTRY CURUSIAFNUM - IAF TERMINAL NUMBER.
  492. * USERJSN[CURUSER] - JSN OF THE USER'S JOB.
  493. *
  494. * EXIT WORKNAM - CORRECT NAME.
  495. #
  496. C<0,2>WORKNAM="WK";
  497. C<2,4>WORKNAM=USERJSN[CURUSER];
  498. C<6,1>WORKNAM=0;
  499. END # OF GENWRKNAM #
  500.  
  501.  
  502. CONTROL IFEQ METERING,1;
  503. PROC ADDVECT(VECTOR,DATA);
  504. BEGIN
  505. #
  506. ** ADDVECT - ADD DATA INTO A STATISTICS VECTOR.
  507. *
  508. * ADDVECT IS PART OF THE INSTRUMENTATION FEATURE OF SMFEX
  509. * AND SERVES TO INCREMENT THE TOTALS AND ONE VALUE-DEPENDENT
  510. * COUNTER IN A SELECTED VECTOR. THE VECTOR HAS ONE WORD FOR
  511. * TOTAL VALUE AND TOTAL EVENT COUNT, THEN FOUR WORDS EACH
  512. * CONTAINING FOUR 15-BIT COUNTERS. THE COUNTER TO BE
  513. * INCREMENTED IS SELECTED BY THE DATA VALUE, WITH THE FIRST
  514. * COUNTER FOR VALUES OF ZERO, THE SECOND FOR VALUES OF ONE,
  515. * AND THE THIRD THRU SIXTEENTH COUNTER CORRESPONDING TO
  516. * VALUES IN THE RANGE (2**(N-2)) .LE. VALUE .LT. (2**(N-1)).
  517. *
  518. * ENTRY DATA - VALUE TO RECORD.
  519. *
  520. * EXIT VECTOR - UPDATED.
  521. #
  522. ITEM TMP1, TMP2, TMP3 R;
  523. ARRAY VECTOR[0:4]; ITEM WORD;
  524. ITEM DATA;
  525. B<0,30>WORD[0]=B<0,30>WORD[0]+DATA;
  526. B<30,30>WORD[0]=B<30,30>WORD[0]+1;
  527. IF DATA LQ 0 THEN TMP1=0;
  528. ELSE
  529. BEGIN
  530. TMP3=DATA*1.0;
  531. TMP1=B<6,6>TMP3-15;
  532. END
  533. TMP1=MAX(TMP1,0);
  534. TMP1=MIN(TMP1,15);
  535. TMP2=MOD4(TMP1)*15;
  536. TMP1=(TMP1/4)+1;
  537. IF B<TMP2,15>WORD[TMP1] NQ O"77777"
  538. THEN B<TMP2,15>WORD[TMP1]=B<TMP2,15>WORD[TMP1]+1;
  539. END # OF ADDVECT #
  540. CONTROL FI;
  541. PAGE # TRACE ROUTINES FOR DEBUG #
  542.  
  543.  
  544. DEF TCTL # CONTROL IFEQ TRACEFLAG,1; #;
  545. DEF TRCOUT(AA) # TCTL TRACEOUT(AA); CONTROL FI #;
  546. DEF TRCSTR(AA) # TCTL TRACESTR(AA); CONTROL FI #;
  547. DEF TRCDEC(AA) # TCTL TRACEDEC(AA); CONTROL FI #;
  548. DEF TRCFRC # TCTL TRACEFRC; CONTROL FI #;
  549. DEF TRCWORDS(AA,BB) # TCTL TRACEWORDS(AA,BB); CONTROL FI #;
  550. DEF TRCBOTH(AA,BB) # TCTL TRACEBOTH(AA,BB); CONTROL FI #;
  551.  
  552.  
  553. CONTROL IFEQ TRACEFLAG,1;
  554.  
  555. PROC TRACEOUT(TEXT);
  556. BEGIN
  557. ARRAY TEXT[0:99]; ITEM TXTWORD;
  558. ITEM INITED B=FALSE;
  559. ARRAY TRCFET (FETSIZ);;
  560. ARRAY TRCLIN[0:20]; ITEM TRCLINE;
  561. ITEM TRCPTR,TXTPTR;
  562. ARRAY TRCBUFF [0:O"2000"];;
  563.  
  564. IF NOT INITED THEN
  565. BEGIN
  566. INITED=TRUE;
  567. TRCPTR=0;
  568. MAKEFET(TRCFET,"TRACE",TRCBUFF,O"2001");
  569. END
  570. TXTPTR=0;
  571. TRCLINE[TRCPTR]=TXTWORD[TXTPTR];
  572. WHYLE B<48,12>TXTWORD[TXTPTR] NQ 0 DO
  573. BEGIN
  574. TXTPTR=TXTPTR+1;
  575. TRCPTR=TRCPTR+1;
  576. TRCLINE[TRCPTR]=TXTWORD[TXTPTR];
  577. END
  578. FOR TXTPTR=9 STEP -1 WHILE TXTPTR GQ 0
  579. AND C<TXTPTR,1>TRCLINE[TRCPTR] EQ ":"
  580. DO C<TXTPTR,1>TRCLINE[TRCPTR]=" ";
  581. TRCPTR=TRCPTR+1;
  582. TRCLINE[TRCPTR]=0;
  583. IF TRCPTR GQ 07 THEN
  584. BEGIN
  585. WRITEC(TRCFET,TRCLIN);
  586. TRCPTR=0;
  587. END
  588. RETURN;
  589.  
  590. ENTRY PROC TRACEWORDS(TEXT,NWORDS);
  591.  
  592. ITEM NWORDS;
  593.  
  594. IF NOT INITED THEN
  595. BEGIN
  596. INITED=TRUE;
  597. TRCPTR=0;
  598. MAKEFET(TRCFET,"TRACE",TRCBUFF,O"2001");
  599. END
  600. IF TRCPTR NQ 0 THEN
  601. BEGIN
  602. WRITEC(TRCFET,TRCLIN);
  603. TRCPTR=0;
  604. END
  605. WRITEW(TRCFET,TEXT,NWORDS);
  606. IF B<48,12>TXTWORD[NWORDS-1] NQ 0 THEN WRITEW(TRCFET,0,1);
  607. RETURN;
  608.  
  609. ENTRY PROC TRACEFRC;
  610.  
  611. IF TRCPTR NQ 0 THEN
  612. BEGIN
  613. WRITEC(TRCFET,TRCLIN);
  614. TRCPTR=0;
  615. END
  616. WRITER(TRCFET,1);
  617.  
  618. END # OF TRCOUT #
  619.  
  620.  
  621. PROC TRACESTR(STR);
  622. BEGIN
  623.  
  624. ITEM STR C(40);
  625.  
  626. ARRAY TEXT [0:4]; ITEM TXTWORD;
  627. ITEM TMP1;
  628.  
  629. TXTWORD[0]=0;
  630. FOR TMP1=0 STEP 1 WHILE TMP1 LQ 39 AND C<TMP1,1>STR NQ "$" DO
  631. BEGIN
  632. C<MOD(TMP1,10),1>TXTWORD[TMP1/10]=C<TMP1,1>STR;
  633. TXTWORD[1+TMP1/10]=0;
  634. END
  635. TRCOUT(TEXT);
  636.  
  637. END # OF TRCSTR #
  638.  
  639.  
  640. PROC TRACEDEC(NUM);
  641. BEGIN
  642. ITEM NUM;
  643. ITEM TMP1,TMP2,TMP3;
  644.  
  645. TMP1=NUM;
  646. TMP2=O"55555555555555330000";
  647. TMP3=7;
  648. IF TMP1 LS 0 THEN
  649. BEGIN
  650. C<0,1>TMP2="-";
  651. TMP1=-TMP1;
  652. END
  653. WHYLE TMP1 NQ 0 DO
  654. BEGIN
  655. C<TMP3,1>TMP2=O"33"+MOD(TMP1,10);
  656. TMP3=TMP3-1;
  657. TMP1=TMP1/10;
  658. END
  659. TRCOUT(TMP2);
  660.  
  661. END # OF TRCDEC #
  662.  
  663.  
  664. PROC TRACEBOTH(AA,BB);
  665. BEGIN
  666. ARRAY AA;;
  667. ARRAY BB;;
  668. TRCSTR(AA);
  669. TRCDEC(BB);
  670. END # OF TRCBOTH #
  671.  
  672. CONTROL FI;
  673. PAGE # UTIITIES FOR QUEUES, CHAINS, TABLES #
  674.  
  675.  
  676. PROC GETUSER;
  677. BEGIN
  678. #
  679. ** GETUSER - MAKE TABLE ENTRIES ACCESSIBLE FOR CURRENT USER.
  680. *
  681. * GETUSER UNPACKS THE DENSELY FORMATTED, INDEXABLE USER
  682. * TABLE INTO THE SPARSE, NONINDEXABLE USER TABLE. THE DENSE
  683. * TABLE PROVIDES CONSERVATION OF MEMORY CAPACITY, WHILE
  684. * THE SPARSE TABLE PROVIDES CONSERVATION OF CODE SIZE AND
  685. * TIMING FOR FREQUENT REFERENCES.
  686. *
  687. * ENTRY CURUSER - INDEX FOR WHICH USER.
  688. * USERTAB[CURUSER] - "DENSE PACK" FORMATTED TABLE.
  689. *
  690. * EXIT CURUSERTAB - EXPANDED COPY OF USERTAB.
  691. *
  692. * CALLS GETUTAB.
  693. #
  694. BASED ARRAY PARM;;
  695. P<PARM>=LOC(USERTAB[CURUSER]);
  696. GETUTAB(PARM,CURUSERTAB);
  697. END # OF GETUSER #
  698.  
  699.  
  700. PROC PUTUSER;
  701. BEGIN
  702. #
  703. ** PUTUSER - PRESERVE TABLE ENTRIES IN DENSE TABLE.
  704. *
  705. * PUTUSER IS CALLED TO COPY AND PACK THE SPARSELY FORMATTED,
  706. * NON-INDEXABLE USER TABLE INTO THE DENSELY FORMATTED,
  707. * INDEXABLE TABLE. PUTUSER IS THUS THE OPPOSITE OF
  708. * GETUSER. NOTE THAT THE SPARSE TABLE IS TEMPORARY AND
  709. * THE DENSE TABLE IS PERMANENT.
  710. *
  711. * ENTRY CURUSER - CURRENT USER.
  712. * CURUSERTAB - SPARSE TABLE.
  713. *
  714. * EXIT USERTAB[CURUSER] - PACKED VERSION OF TABLE.
  715. *
  716. * CALLS SAVUTAB.
  717. #
  718. BASED ARRAY PARM;;
  719. P<PARM>=LOC(USERTAB[CURUSER]);
  720. SAVUTAB(PARM,CURUSERTAB);
  721. END # OF PUTUSER #
  722.  
  723.  
  724. PROC GETCOMMON;
  725. BEGIN
  726. #
  727. ** GETCOMMON - GET STORAGE FOR RIGHT TASK INTO COMMON.
  728. *
  729. * TO CONSERVE CPU TIME REQUIRED FOR SHUFFLING OF THE COMMON
  730. * BLOCK IN MULTI-TASKING, THE COMMON BLOCK IS LEFT VOLATILE
  731. * WHEN ONE TASK GIVES UP THE CPU IN THE HOPE THAT THE SAME
  732. * TASK WILL BE THE NEXT TO USE THE CPU. WHEN A DIFFERENT
  733. * TASK IS NEXT ON THE CPU, THEN WE MUST PERFORM THE DEFERRED
  734. * COPYING OF COMMON TO/FROM TASK DISPATCHING AREAS.
  735. *
  736. * ENTRY LASTTASK - TASK WHICH MOST RECENTLY USED COMMON.
  737. * ZERO INDICATES COMMON IS NOT VOLATILE.
  738. * CURTASK - TASK WHICH NEEDS COMMON.
  739. * TASKSWPNOW[LASTTASK], TASKSWPIN[LASTTASK] -
  740. * INDICATE IF VOLATILITY SUPPRESSED BY
  741. * CURRENTLY ACTIVE SWAPIN.
  742. *
  743. * EXIT LASTTASK - EQUALS CURTASK.
  744. * COMMON BLOCK - SAVED IN LASTTASK IF NEEDED,
  745. * UPDATED FOR CURTASK IF NEEDED.
  746. *
  747. * CALLS MOVEWD.
  748. *
  749. * USES P<MOVFROM>, P<MOVTO>.
  750. #
  751. IF LASTTASK NQ 0 AND LASTTASK NQ CURTASK AND
  752. NOT (TASKSWPNOW[LASTTASK] AND TASKSWPIN[LASTTASK]) THEN
  753. BEGIN
  754. P&lt;MOVTO>=TASKDSPADR[LASTTASK];
  755. MOVEWD(DISPATLEN,DATASTART,MOVTO);
  756. END
  757. IF LASTTASK NQ CURTASK THEN
  758. BEGIN
  759. P&lt;MOVFROM>=TASKDSPADR[CURTASK];
  760. MOVEWD(DISPATLEN,MOVFROM,DATASTART);
  761. END
  762. LASTTASK=CURTASK;
  763. END # OF GETCOMMON #
  764.  
  765.  
  766. PROC PUTCOMMON;
  767. BEGIN
  768. #
  769. ** PUTCOMMON - COPY COMMON INTO DISPATCHING AREA.
  770. *
  771. * PUTCOMMON IS CALLED WHEN THE LIVE COMMON BLOCK IS CONSIDERED
  772. * MORE CURRENT THAN THE COMMON IMAGE IN THE TASK DISPATCHING
  773. * AREA, AND REQUIRES IMMEDIATE COPYING.
  774. *
  775. * ENTRY CURTASK - CURRENT TASK.
  776. * TASKDSPADR[CURTASK] - ADDRESS OF DISPATCH AREA.
  777. *
  778. * EXIT DISPATCH AREA - UPDATED FROM DATASTART.
  779. *
  780. * CALLS MOVEWD.
  781. *
  782. * USES P<MOVTO>.
  783. #
  784. # COPY DISPATCHABLE STORAGE FOR THIS TASK OUT OF COMMON #
  785. P&lt;MOVTO>=TASKDSPADR[CURTASK];
  786. MOVEWD(DISPATLEN,DATASTART,MOVTO);
  787. END # OF PUTCOMMON #
  788.  
  789.  
  790. PROC KILL;
  791. BEGIN
  792. #
  793. ** KILL - ERASE USE FROM TABLES.
  794. *
  795. * KILL IS CALLED WHEN DISCONNECTING A USER. IT IS ASSUMED
  796. * THE USER IS NOT IN THE SWAPIN QUEUE. THE USER MAY
  797. * HAVE TERMINAL INPUT BUFFERS, WHICH ARE RELEASED. THEN
  798. * THE TABLE ENTRIES ARE ZEROED.
  799. *
  800. * ENTRY CURUSER - WHO TO KILL.
  801. * CURUSIAFNUM - IAF TERMINAL NUMBER.
  802. *
  803. * EXIT USERTAB[CURUSER], ORDWORD[CURUSIAFNUM] - ZERO.
  804. * CURUSERTAB - ZERO ALSO.
  805. *
  806. * CALLS PURGETTI, PUTUSER, GETUSER.
  807. #
  808. PURGETTI;
  809. USERWORD0[CURUSER]=0;
  810. USERWORD1[CURUSER]=0;
  811. USERWORD2[CURUSER]=0;
  812. GETUSER;
  813. END # OF KILL #
  814.  
  815.  
  816. PROC SCHEDULE;
  817. BEGIN
  818. #
  819. ** SCHEDULE - ASSURE USER WILL RUN IN A TASK SOON.
  820. *
  821. * SCHEDULE IS USED WHENEVER WE RECEIVE A CODE FROM IAFEX,
  822. * ASSURES THE USER WILL BE SCHEDULED FOR TASK SERVICE OR WILL
  823. * BE ADEQUATELY SERVICED IF ALREADY IN A TASK.
  824. *
  825. * ENTRY CURUSER - USER TO BE QUEUED.
  826. * CURUSERTAB - ALL ENTRIES SETUP.
  827. * CURUSINTASK - WHETHER ALREADY SCHEDULED.
  828. * CURUSINQUE - WHETHER ALREADY QUEUED.
  829. * CURUSTASK - WHICH TASK IF CURUSINTASK TRUE.
  830. *
  831. * EXIT USER QUEUED IF NOT ALREADY IN TASK.
  832. * TASKREQUE[] - SET IF IN TASK TO SIGNAL EVENT.
  833. * TASKPULSE[] - SET TO QUICKLY END ANY DELAY.
  834. *
  835. * CALLS PUTINQ.
  836. #
  837. IF CURUSINTASK THEN
  838. BEGIN
  839. TASKREQUE[CURUSTASK]=TRUE; # ASSURE KEEPS RUNNING #
  840. TASKPULSE[CURUSTASK]=3; # ASSURE NO CLOCK DELAY LOOP #
  841. END
  842. ELSE IF NOT CURUSINQUE THEN PUTINQ;
  843.  
  844. END # OF SCHEDULE #
  845.  
  846.  
  847. PROC PUTINQ;
  848. BEGIN
  849. #
  850. ** PUTINQ - PUT CURRENT USER IN SCHEDULE QUEUE.
  851. *
  852. * PUTINQ LINKS THE CURRENT USER ONTO THE QUEUE OF JOBS
  853. * WHICH HAVE BEEN SCHEDULED FOR FUTURE TASK ASSIGNMENT.
  854. * A NEW QUEUE LINKAGE IS STARTED IF THERE IS NO QUEUE
  855. * ALREADY.
  856. *
  857. * ENTRY CURUSER - CURRENT USER.
  858. * CURUSERTAB - ALL ENTRIES SETUP.
  859. * CURUSINQUE - MUST BE FALSE.
  860. * SWPQHEAD - ZERO IF NO QUEUE EXISTS, OR LINK TO HEAD
  861. * OF QUEUE IF OTHER USERS ALREADY QUEUED.
  862. * SWPQTAIL - IF SWPQHEAD NON-TRIVIAL, LAST USER QUEUED.
  863. * SWPQSIZE - NUMBER OF USERS IN QUEUE.
  864. *
  865. * EXIT VIA MELT IF INVALID CONDITIONS.
  866. * SWPQHEAD - HEAD OF QUEUE. (CURUSER IF NEW QUEUE)
  867. * SWPQTAIL - TAIL OF QUEUE NOW EQUALS CURUSER.
  868. * USERQUELNK[OLD SWPQTAIL] - LINKS TO CURUSER IF THERE
  869. * WAS A PREVIOUS QUEUE.
  870. * CURUSINQUE - TRUE.
  871. * SWPQSIZE - INCREMENTED.
  872. *
  873. * CALLS MELT.
  874. #
  875. CONTROL IFGQ PARANOIA,5;
  876. IF CURUSINQUE THEN MELT("PUTINQ 1$");
  877. CONTROL FI;
  878. IF SWPQHEAD EQ 0 THEN # NEW QUEUE #
  879. BEGIN
  880. SWPQHEAD=CURUSER;
  881. SWPQTAIL=CURUSER;
  882. CURUSQUELNK=0;
  883. END
  884. ELSE # APPEND TO QUEUE #
  885. BEGIN
  886. USERQUELNK[SWPQTAIL]=CURUSER;
  887. CURUSQUELNK=0;
  888. SWPQTAIL=CURUSER;
  889. END
  890. CURUSINQUE=TRUE;
  891. SWPQSIZE=SWPQSIZE+1;
  892.  
  893. END # OF PUTINQ #
  894.  
  895.  
  896. PROC TAKEOFFQ;
  897. BEGIN
  898. #
  899. ** TAKEOFFQ - TAKE CURRENT USER OFF QUEUE.
  900. *
  901. * TAKEOFFQ REMOVES THE CURRENT USER FROM THE QUEUE OF USERS
  902. * SCHEDULED FOR FUTURE TASK ASSIGNMENT. THE CURRENT USER IS
  903. * REQUIRED TO BE IN THE QUEUE, BUT IS ALLOWED TO BE AT THE
  904. * HEAD, OR AT THE TAIL, OR ANYWHERE IN BETWEEN. TAKEOFFQ
  905. * THEREFORE CONTAINS LOGIC TO CLOSE QUEUE LINKAGE UP AROUND
  906. * THE EXTRACTED USER.
  907. *
  908. * ENTRY CURUSER - CURRENT USER.
  909. * CURUSERTAB - ALL ENTRIES SETUP.
  910. * CURUSINQUE - MUST BE TRUE.
  911. * SWPQHEAD - HEAD OF QUEUE.
  912. * SWPQTAIL - TAIL OF QUEUE.
  913. * SWPQSIZE - NUMBER OF USERS IN QUEUE.
  914. * USERQUELNK[ALL IN QUEUE] - LINKAGE.
  915. *
  916. * EXIT CURUSINQUE - FALSE.
  917. * CURUSQUELNK - ZEROED OUT.
  918. * SWPQTAIL - BACKED TO PREVIOUSLY NEXT-TO-LAST
  919. * USER IF CURUSER MATCHED SWPQTAIL.
  920. * SWPQHEAD - ADVANCED TO PREVIOUSLY SECOND USER IF
  921. * CURUSER MATCHED SWPQHEAD. ZERO IF CURUSER WAS
  922. * ONLY USER IN QUEUE.
  923. * SWPQSIZE - DECREMENTED.
  924. *
  925. * CALLS MELT.
  926. #
  927. ITEM TMP1,TMP2;
  928.  
  929. CONTROL IFGQ PARANOIA,5;
  930. IF NOT CURUSINQUE THEN MELT("TAKEOFFQ 1$");
  931. CONTROL FI;
  932. IF SWPQHEAD EQ CURUSER THEN # TAKE FROM FRONT #
  933. BEGIN
  934. IF SWPQHEAD EQ SWPQTAIL THEN SWPQTAIL=0;
  935. SWPQHEAD=CURUSQUELNK;
  936. END
  937. ELSE # FIND THEN EXTRACT #
  938. BEGIN
  939. TMP1=SWPQHEAD;
  940. WHYLE TMP1 NQ CURUSER DO
  941. BEGIN
  942. CONTROL IFGQ PARANOIA,5;
  943. IF TMP1 EQ 0 THEN MELT("TAKEOFFQ 2$");
  944. CONTROL FI;
  945. TMP2=TMP1;
  946. TMP1=USERQUELNK[TMP1];
  947. END
  948. IF TMP1 EQ SWPQTAIL THEN SWPQTAIL=TMP2;
  949. USERQUELNK[TMP2]=USERQUELNK[TMP1];
  950. END
  951. CURUSINQUE=FALSE;
  952. CURUSQUELNK=0;
  953. SWPQSIZE=SWPQSIZE-1;
  954.  
  955. END # OF TAKEOFFQ #
  956.  
  957.  
  958. PROC ALLOC(BITMAP,BITMASK,INDEX,LIMIT);
  959. BEGIN
  960. #
  961. ** ALLOC - ALLOCATE RESOURCE VIA BITMAP.
  962. *
  963. * SEARCH THE BITMAP FOR AN AVAILABLE ENTITY, RETURN THE INDEX
  964. * FOR IT. SET THE BIT AS UNAVAILABLE. BITMAPS ARE 32-BITS
  965. * PER WORD, CENTERED, SO THAT THE FINDBIT ROUTINE CAN USE
  966. * OPTIMAL INSTRUCTIONS (E.G., NORMALIZE) TO FIND A BIT. A
  967. * BIT IS ON TO SHOW AVAILABLE ENTITY.
  968. *
  969. * ENTRY BITMAP - THE BITMAP ARRAY TO SEARCH AND UPDATE.
  970. * BITMASK - ARRAY WITH "DONT USE" FLAGS.
  971. * LIMIT - SIZE OF ARRAYS.
  972. *
  973. * EXIT INDEX - ORDINAL OF ALLOCATED RESOURCE.
  974. * BITMAP - UPDATED TO REFLECT ALLOCATION.
  975. *
  976. * CALLS FINDBIT.
  977. #
  978. ARRAY BITMAP[0:99]; ITEM BITWORD;
  979. ARRAY BITMASK;;
  980. ITEM INDEX, LIMIT;
  981.  
  982. INDEX=FINDBIT(LIMIT,BITMAP,BITMASK);
  983. IF INDEX NQ -1 THEN B&lt;12+MOD32(INDEX),1>BITWORD[INDEX/32]=0;
  984. INDEX=INDEX+1; # ADJUST TO ORIGIN OF ONE #
  985.  
  986. END # OF ALLOC #
  987.  
  988.  
  989. PROC DEALLOC(BITMAP,INDEX,LIMIT);
  990. BEGIN
  991. #
  992. ** DEALLOC - UPDATED BITMAP TO MAKE RESOURCE AVAILABLE.
  993. *
  994. * DEALLOC IS THE COUNTERPART TO ALLOC.
  995. *
  996. * ENTRY BITMAP - ARRAY CONTAINING ALLOCATION FLAGS.
  997. * INDEX - WHICH RESOURCE TO FREE UP.
  998. * LIMIT - SIZE OF BITMAP.
  999. *
  1000. * EXIT BITMAP - UPDATED.
  1001. *
  1002. * CALLS MELT.
  1003. #
  1004. ITEM INDEX, LIMIT;
  1005. ARRAY BITMAP [0:99]; ITEM BITWORD;
  1006. ITEM TMP1;
  1007. TMP1=INDEX-1;
  1008. CONTROL IFGQ PARANOIA,5;
  1009. IF TMP1 GQ LIMIT*32 OR TMP1 LS 0 THEN MELT("DEALLOC 1$");
  1010. IF B&lt;12+MOD32(TMP1),1>BITWORD[TMP1/32] EQ 1
  1011. THEN MELT("DEALLOC 2$");
  1012. CONTROL FI;
  1013. B&lt;12+MOD32(TMP1),1>BITWORD[TMP1/32]=1;
  1014. END # OF DEALLOC #
  1015.  
  1016.  
  1017. PROC FORCEALLOC(BITMAP,INDEX,LIMIT);
  1018. BEGIN
  1019. #
  1020. ** FORCEALLOC - ALLOCATE SPECIFIC RESOURCE WITHOUT SEARCH.
  1021. *
  1022. * FORCES A BIT AS UNAVAIL. USED TO CUT OFF EXCESS BITS AT
  1023. * END OF A BITMAP AND TO SHUT OFF ENTITIES THAT HAVE SUFFERED
  1024. * HARDWARE FAILURES. (SUCH AS SEGMENTS OF ECS)
  1025. *
  1026. * ENTRY BITMAP - ARRAY OF ALLOCATION FLAGS.
  1027. * INDEX - WHICH RESOURCE TO ALLOCATE.
  1028. * LIMIT - SIZE OF BITMAP.
  1029. *
  1030. * EXIT BITMAP - UPDATED.
  1031. *
  1032. * CALLS MELT.
  1033. #
  1034. ITEM INDEX,LIMIT;
  1035. ARRAY BITMAP[0:99]; ITEM BITWORD;
  1036. ITEM TMP1;
  1037.  
  1038. TMP1=INDEX-1;
  1039. CONTROL IFGQ PARANOIA,5;
  1040. IF TMP1 GQ LIMIT*32 OR TMP1 LS 0 THEN MELT("FORCEALLOC 1$");
  1041. CONTROL FI;
  1042. B&lt;12+MOD32(TMP1),1>BITWORD[TMP1/32]=0;
  1043.  
  1044. END # OF FORCEALLOC #
  1045.  
  1046.  
  1047. PROC KILLECSBITS(BITMAP);
  1048. BEGIN
  1049. #
  1050. ** KILLECSBITS - FORCEALLOC ALL ECS SWAP PAGES.
  1051. *
  1052. * ENTRY BITMAP - ARRAY OF ALLOCATION FLAGS TO UPDATE.
  1053. *
  1054. * BITMAP - UPDATED.
  1055. *
  1056. * CALLS FORCEALLOC.
  1057. #
  1058. ARRAY BITMAP;;
  1059. ITEM TMP1;
  1060. FOR TMP1=1 STEP 1 UNTIL NUMSWPECS
  1061. DO FORCEALLOC(BITMAP,TMP1,NUMSWPBIT);
  1062. END # OF KILLECSBITS #
  1063.  
  1064.  
  1065. PROC PURGETTI;
  1066. BEGIN
  1067. #
  1068. ** PURGETTI - GET RID OF ANY TERMINAL INPUT CHAINS.
  1069. *
  1070. * ENTRY CURUSER - CURRENT USER.
  1071. * CURUSTTIBUF - FIRST TTI BUFFER OR NULL.
  1072. * REMAINTTI - HOW MANY BUFFERS STILL AVAIL.
  1073. * TTIBUFLNK[ALL] - LINKAGES.
  1074. * TTIBITS - ALLOCATION BITMASK.
  1075. *
  1076. * EXIT CURUSTTIBUF - NULL.
  1077. * REMAINTTI - INCREMENTED.
  1078. * TTIBITS - UPDATED.
  1079. *
  1080. * CALLS DEALLOC.
  1081. #
  1082. ITEM TMP1;
  1083. TRCSTR("PURGETTI$");
  1084. TMP1=CURUSTTIBUF;
  1085. WHYLE TMP1 NQ 0 DO
  1086. BEGIN
  1087. CURUSTTIBUF=0;
  1088. DEALLOC(TTIBITS,TMP1,NUMTTIBIT);
  1089. REMAINTTI=REMAINTTI+1;
  1090. TMP1=TTIBUFLNK[TMP1];
  1091. END
  1092. END # OF PURGETTI #
  1093. PAGE # MAJOR SYSTEM STATE ROUTINES #
  1094.  
  1095.  
  1096. PROC DROPSLICE;
  1097. BEGIN
  1098. #
  1099. ** DROPSLICE - RECALL CPU FOR A LITTLE WHILE.
  1100. *
  1101. * ENTRY NO CONDITIONS.
  1102. *
  1103. * EXIT REAL TIME HAS BEEN DELAYED.
  1104. *
  1105. * CALLS RECALL, INSTRMNT1.
  1106. #
  1107. RECALL(0);
  1108. CONTROL IFEQ METERING,1;
  1109. INSTRMNT1(INSTST"CLOCKTICK");
  1110. CONTROL FI;
  1111.  
  1112. END # OF DROPSLICE #
  1113.  
  1114.  
  1115. PROC DOTIMER;
  1116. BEGIN
  1117. #
  1118. ** DOTIMER - SUPERVISE TIME DEPENDENCIES.
  1119. *
  1120. * DOTIMER IS INTENDED TO BE CALLED ONCE PER MAIN LOOP. THE
  1121. * CPU IS RECALLED ONCE TO ACHIEVE A SMALL DELAY IN REAL TIME,
  1122. * ABOUT 24 MILLISECONDS IF THE INSTALLATION RUNS WITH DEFAULT
  1123. * OPERATOR PARAMETERS, THE TIME OF DAY IS NOTED, AND CERTAIN
  1124. * FUNCTIONS ARE PERFORMED IF THE TIME OF DAY HAS ADVANCED
  1125. * SUFFICIENTLY SINCE THE LAST TIME SUCH FUNCTIONS WERE
  1126. * PERFORMED.
  1127. *
  1128. * ON A CYCLE OF APPROX FIVE TIMES PER SECOND, WE LOOK FOR
  1129. * OPERATOR COMMANDS AND SIGNAL RESTART OF ANY TASKS WHICH ARE
  1130. * DELAYING FOR THE PURPOSE OF ACHIEVING A QUICK RECYCLE OF
  1131. * THE SAME TASK FOR THE SAME USER.
  1132. *
  1133. * ON A CYCLE OF APPROX TWO SECONDS, THE B-DISPLAY MESSAGE IS
  1134. * UPDATED TO SHOW CURRENT LOAD PARAMETERS - NUMBER OF USERS
  1135. * IN THE SUBSYSTEM AND NUMBER OF TASKS CURRENTLY ASSIGNED TO
  1136. * EXECUTE.
  1137. *
  1138. * ENTRY TIMEOFDAY - TIME AT WHICH PREVIOUS CPU SLICE STARTED.
  1139. * NEWTIMEDAY - EQUALS TIMEOFDAY OR TIME AT WHICH A TASK
  1140. * WAS CONSIDERED FOR PREEMPTIVE SWAP, WHICHEVER LARGER.
  1141. * SLICECOUNT - NUMBER OF CYCLES EXECUTED SO FAR.
  1142. * LOGGEDIN - NUMBER OF USERS.
  1143. * TASKSBUSY - NUMBER OF TASKS UTILIZED.
  1144. * ENABLEFLAG - ENABLE/DISABLE NEW USERS OR NO-OP.
  1145. *
  1146. * EXIT OLDTIMEDAY - PREVIOUS VALUE FOR TIMEOFDAY.
  1147. * TIMEOFDAY, NEWTIMEDAY - CURRENT TIME.
  1148. * SLICECOUNT - INCREMENTED.
  1149. * SHUTDOWN, SENSE SWITCHES - REFER TO DOOPER ROUTINE.
  1150. * TASKPULSE[ALL] - 1 IF 5-HERTZ CYCLE OCCURRED.
  1151. * B-DISPLAY UPDATED IF 2-SECOND CYCLE.
  1152. *
  1153. * CALLS DROPSLICE, DOOPER, RTIME, SMFSSTF, SFMCSTF,
  1154. * CHECKTIME(INTERNAL), MESSAGE.
  1155. #
  1156. # HANDLES TIME-OF-DAY DEPENDENT STUFF #
  1157.  
  1158. ITEM LAST5HZ=0, LAST2SEC=0;
  1159. ITEM TMP1, TMP2, BOOL B;
  1160.  
  1161. PROC CHECKTIME(LAST,INTERVAL,FLAG);
  1162. BEGIN
  1163. ITEM LAST, INTERVAL, FLAG B;
  1164. FLAG=FALSE;
  1165. IF TIMEOFDAY-LAST GQ INTERVAL THEN
  1166. BEGIN
  1167. LAST=TIMEOFDAY;
  1168. FLAG=TRUE;
  1169. END
  1170. END # OF CHECKTIME #
  1171.  
  1172.  
  1173. # DOTIMER MAIN CODE STARTS HERE #
  1174.  
  1175. DROPSLICE; # RECALL FOR A WHILE #
  1176. OLDTIMEDAY=NEWTIMEDAY;
  1177. RTIME(TIMEOFDAY);
  1178. B&lt;0,30>TIMEOFDAY=0; # DONT NEED UPPER PART #
  1179. NEWTIMEDAY=TIMEOFDAY;
  1180. SLICECOUNT=SLICECOUNT+1;
  1181.  
  1182. IF ENABLEFLAG NQ 0 THEN
  1183. BEGIN
  1184. IF ENABLEFLAG GQ 0 AND SHUTDOWN EQ 0 THEN SFMSSTF;
  1185. IF ENABLEFLAG LS 0 THEN SFMCSTF;
  1186. ENABLEFLAG=0;
  1187. END
  1188.  
  1189. CHECKTIME(LAST5HZ,200,BOOL); # 5 TIMES PER SECOND #
  1190. IF BOOL THEN
  1191. BEGIN
  1192. DOOPER; # LOOK FOR OPERATOR COMMANDS #
  1193. # ACTIVATE ANY TASKS THAT ARE SPINNING WHEELS #
  1194. FOR CURTASK=1 STEP 1 UNTIL NUMTASKS DO TASKPULSE[CURTASK]=3;
  1195. END
  1196.  
  1197. CHECKTIME(LAST2SEC,2000,BOOL); # ONCE EVERY TWO SECONDS #
  1198. IF BOOL THEN
  1199. BEGIN
  1200. # DISPLAY LOAD FACTORS #
  1201. TMP1=LOGGEDIN;
  1202. FOR TMP2=3 STEP -1 UNTIL 0 DO
  1203. BEGIN
  1204. C&lt;TMP2,1>STATUSMSG=MOD(TMP1,10)+O"33";
  1205. TMP1=TMP1/10;
  1206. END
  1207. C&lt;12,1>STATUSMSG=O"33"+MOD(TASKSBUSY,10);
  1208. C&lt;11,1>STATUSMSG=O"33"+MOD(TASKSBUSY/10,10);
  1209. C&lt;28,2>STATUSMSG=0;
  1210. MESSAGE(STATUSMSG,1,1);
  1211. END
  1212.  
  1213. END # OF DOTIMER #
  1214.  
  1215.  
  1216. PROC DOOPER;
  1217. BEGIN
  1218. #
  1219. ** DOOPER - PERFORM OPERATOR FUNCTIONS.
  1220. *
  1221. * DOOPER SHOULD BE CALLED FROM TIME TO TIME TO SEE IF THE
  1222. * ENVIRONMENT INDICATES AN OPERATIONAL CHANGE IS OCCURRING.
  1223. *
  1224. * THE FIRST ISSUANCE OF "IDLE,SMF." INDICATES THAT SMFEX
  1225. * SHOULD ENROLL NO NEW USERS AND SHOULD TRANSITION EXISTING
  1226. * USERS BACK TO THEIR SINGLE-USER EDITORS WITH COMPLETE
  1227. * TRANSPARENCY. THIS CAN BE DONE AS THE USERS CYCLE THROUGH
  1228. * THE MAIN LOOP OF THE EDITOR. WHEN THE USER COUNT REACHES
  1229. * ZERO, SMFEX WILL SHUT DOWN.
  1230. *
  1231. * A SECOND ISSUE OF THE IDLE COMMAND REQUESTS THAT SMFEX GET
  1232. * OUT OF THE SYSTEM MORE RAPIDLY, POSSIBLY AT THE EXPENSE OF
  1233. * SOME USERS RECEIVING INTERRUPT WARNING MESSAGES BUT STILL
  1234. * WITH NO LOSS OF DATA. SMFEX CAN STOP AS QUICKLY AS IT CAN
  1235. * GET ANY CURRENT TASKS TO LEAVE THEIR INTERNAL CONTROL POINTS.
  1236. *
  1237. * A THIRD ISSUE OF THE IDLE COMMAND REQUESTS EVEN MORE RAPID
  1238. * SHUTDOWN. ANY CURRENT TASKS WILL BE PAUSED AT THEIR NEXT
  1239. * CIO RECALL. THUS SOME USER COMMANDS MAY NOT COMPLETE, BUT
  1240. * NO EDIT SESSIONS WILL SUFFER REGRESSIVE DAMAGE.
  1241. *
  1242. * ANY TIME DOOPER DETECTS EITHER THE SLOWDOWN MODE OR THE
  1243. * QUICK IDLE MODE, IT SETS THE ENABLEFLAG SO THAT DOTIMER
  1244. * WILL DISABLE THE ACCESSABILITY OF THE SUBSYSTEM.
  1245. *
  1246. * ENTRY SHUTDOWN - PREVIOUS SHUTDOWN LEVEL IF ANY.
  1247. * 0 = NORMAL PROCESSING.
  1248. * 1 = ACCEPT NO USERS, KEEP RUNNING.
  1249. * 2 = SPECIAL FOR RECOVERY FUNCTION.
  1250. * 3 = SHUTDOWN WHEN TASKS BECOME EMPTY.
  1251. * 4 = SHUTDOWN WHEN CIO CALLS COMPLETE.
  1252. * SWAPGOOD, SWAPBAD - EXTENDED MEMORY CONTROLS.
  1253. *
  1254. * EXIT SHUTDOWN - UPDATED.
  1255. * MEM[0] - UPDATED TO ACKNOWLEDGE IDLE COMMAND.
  1256. * ENABLEFLAG - FORCED NEGATIVE IF DETECT NEW NON-TRIVIAL
  1257. * VALUE FOR SHUTDOWN FLAG.
  1258. #
  1259. ITEM TMP1;
  1260.  
  1261. IF SHUTDOWN EQ 2 THEN RETURN;
  1262.  
  1263. IF MEM[0] LAN O"100000" NQ 0 THEN # IDLE,SMF. #
  1264. BEGIN
  1265. IF IDLEDOWN THEN STOPNOW=TRUE;
  1266. ELSE IF ACCEPTNONE THEN IDLEDOWN=TRUE;
  1267. ELSE ACCEPTNONE=TRUE;
  1268. MEM[0]=MEM[0] LXR O"100000"; # ACKNOWLEDGE IDLE COMMAND #
  1269. ONSW(O"40"); # SIGNAL SUBSYSTEM TERMINATION #
  1270. END
  1271.  
  1272. TMP1=0;
  1273. IF ACCEPTNONE THEN TMP1=1;
  1274. IF IDLEDOWN THEN TMP1=3;
  1275. IF STOPNOW THEN TMP1=4;
  1276.  
  1277. IF SHUTDOWN NQ TMP1 THEN
  1278. BEGIN
  1279. IF TMP1 NQ 0 THEN ENABLEFLAG=-1;
  1280. ELSE ENABLEFLAG=1;
  1281. END
  1282. SHUTDOWN=TMP1;
  1283.  
  1284. CONTROL IFEQ ECSCODE,1;
  1285. IF ECSDOWN THEN P&lt;SWAPMASK>=LOC(SWAPBAD);
  1286. ELSE P&lt;SWAPMASK>=LOC(SWAPGOOD);
  1287. CONTROL FI;
  1288.  
  1289. END # OF DOOPER #
  1290. PAGE # DOINPUT -- RECEIVE SIC MSG AND QUEUE #
  1291.  
  1292.  
  1293. PROC DOINPUT;
  1294. BEGIN
  1295. #
  1296. ** DOINPUT - ACCEPT MESSAGES FROM IAFEX.
  1297. *
  1298. * DOINPUT SUPERVISES ALL MESSAGE RECEIVED FROM IAF, AND
  1299. * SHOULD BE CALLED BY THE MAIN LOOP ONCE PER RECALL CYCLE.
  1300. * IAF COMMUNICATES WITH SMF BY USING THE SCP/UCP FACILITY
  1301. * (IAF IS THE SCP AND SMF IS THE UCP) TO PLACE MESSAGES
  1302. * INSIDE THE SMF FIELD LENGTH. THE ADDRESS OF THE SMF WINDOW
  1303. * FOR MESSAGES WAS ESTABLISHED BY SMF WHEN IT FIRST SENT A
  1304. * MESSAGE TO IAF. IAF CANNOT SEND ITS NEXT MESSAGE UNTIL SMF
  1305. * ACKNOWLEDGES THE CURRENT MESSAGE BY CLEARING THE HEADER
  1306. * WORD.
  1307. *
  1308. * NOTE THAT THE DOINPUT ROUTINE PROCESSES RECEIPT OF
  1309. * MESSAGES, BUT HAS NOTHING TO DO WITH SENDING MESSAGES TO
  1310. * IAFEX. THAT FUNCTION IS PROVIDED AS TASKS EXECUTE VIA
  1311. * EXECUTIVE ROUTINES CALLED BY THE EDITOR MODULE. DOINPUT
  1312. * CAN TRANSMIT A MESSAGE TO IAFEX, BUT ONLY UNDER THE
  1313. * EMERGENCY SITUATION WHERE THE USER TABLE HAS OVERFLOWED, IN
  1314. * WHICH CASE THE USER BEING CONNECTED MUST BE IMMEDIATELY
  1315. * DISCONNECTED BEFORE ANY OTHER SMFEX PROCESSING CAN PROCEED.
  1316. * THIS SITUATION IS NORMALLY DISCOURAGED BY LOGIC TO DISABLE
  1317. * SMFEX SUBSYSTEM ACCESSABILITY WHEN THE USER TABLE GETS
  1318. * CLOSE TO THE FULL CONDITION.
  1319. *
  1320. * MESSAGES FROM IAF ARE OF TWO BASIC FORMS - FIRST, A
  1321. * QUICK-SHUTDOWN IS INDICATED BY NON-ZERO CONTENT APPEARING
  1322. * IN SSCINP[-1], AND SECOND, A PRODUCTION MESSAGE IS
  1323. * INDICATED BY NON-ZERO CONTENT IN ONE OR MORE WORDS STARTING
  1324. * WITH SSCINP[0].
  1325. *
  1326. * PRODUCTION MESSAGES CAN APPEAR IN SIX VARIATIONS - (1)
  1327. * INITIALIZATION OF IAF, (2) COMMAND TEXT, (3)
  1328. * ACKNOWLEDGEMENT THAT OUTPUT HAS BEEN RECEIVED AND MORE CAN
  1329. * BE ACCEPTED, (4) USER BREAK, (5) DETACHMENT OF TERMINAL
  1330. * FROM JOB, AND (6) CONNECTION OF A NEW USER INTO SMFEX.
  1331. *
  1332. * THE SECOND THRU FIFTH MESSAGE TYPES REQUIRE REFERENCE TO AN
  1333. * EXISTING USER WITHIN SMFEX. THE SECOND MESSAGE TYPE
  1334. * CARRIES ARBITRARY TEXT ALONG WITH THE HEADER WORD, AND THE
  1335. * SIXTH MESSAGE TYPE CARRIES ONE WORD OF TEXT WITH THE HEADER
  1336. * WORD. THE OTHER MESSAGE TYPES CONSIST SOLELY OF THE HEADER
  1337. * WORD.
  1338. *
  1339. * COMMAND MESSAGES CAUSE SCHEDULING OF THE USER FOR TASK
  1340. * PROCESSING, AND TO ENABLE THE RECEIPT OF ADDITIONAL
  1341. * MESSAGES FROM IAF WHILE THE TASK SWAPS IN, THE MESSAGE TEXT
  1342. * IS QUEUED IN ONE OF THE TERMINAL INPUT BUFFERS. SINCE ONE
  1343. * COMMAND MESSAGE MAY BE JUST A FRAGMENT OF THE ENTIRE
  1344. * COMMAND TEXT, INPUT BUFFERS ARE LINKED TO THE USER AND TO
  1345. * EACH OTHER AS NEEDED.
  1346. *
  1347. * SMFEX ATTEMPTS TO AVOID RUNNING OUT OF INPUT BUFFERS WITH
  1348. * "TRY HARDER" TASK SCHEDULING RULES, BUT IF BUFFERS DO GET
  1349. * EXHAUSTED, THEN DOINPUT SIMPLY NEGLECTS TO CLEAR AWAY THE
  1350. * IAF WINDOW AT SSCINP[0], THUS PREVENTING IAF FROM SENDING
  1351. * MORE MESSAGES UNTIL WE CATCH UP AND CAUSING FUTURE DOINPUT
  1352. * CYCLES TO ONCE AGAIN ATTEMPT TO QUEUE THE INPUT. IN THE
  1353. * EXTREME CASE WHERE SMFEX FALLS BEHIND WITH IAFEX HOLDING 64
  1354. * MESSAGES IN ITS OWN QUEUE, THEN IAFEX WILL TREAT SMFEX AS A
  1355. * DERELICT AND REVERT ALL USERS BACK TO SINGLE-USER MODE.
  1356. *
  1357. * USER BREAKS AND DETACHMENTS CAUSE TASK SCHEDULING WITH
  1358. * APPROPRIATE FLAGS SET SO THE TASK WILL INTERRUPT NORMAL
  1359. * PROCESSING AND REACT ACCORDINGLY. FOR DETACHMENT, IAF
  1360. * DELAYS DETACH COMPLETION UNTIL SMFEX FINALLY TRANSMITS AN
  1361. * END-OF-EDIT MESSAGE.
  1362. *
  1363. * OUTPUT ACCEPTANCE MESSAGES CAUSE TASK SCHEDULING FOR
  1364. * CONTINUED EXECUTION.
  1365. *
  1366. * CONNECTION MESSAGES CAUSE SMFEX TO ALLOCATE A NEW TABLE
  1367. * ENTRY FOR THE USER, SAVING THE JSN AND EJT ORDINAL PROVIDED
  1368. * IN THE SECOND WORD OF THE MESSAGE, WITH THE NEW USER
  1369. * SCHEDULED FOR TASK EXECUTION SO THAT THE TRANSFERRED
  1370. * WORKFILE CAN BE QUICKLY VALIDATED.
  1371. *
  1372. * ENTRY SSCINP[-1] - AS CLEARED BY PREVIOUS DOINPUT, OR
  1373. * NEW SHUTDOWN MESSAGE FROM IAFEX.
  1374. * SSCINP[0] - AS CLEARED BY PREVIOUS DOINPUT, OR
  1375. * HEADER OF NEW MESSAGE FROM IAFEX.
  1376. * SHUTDOWN - WHETHER TO PROCESS INPUT NORMALLY.
  1377. * USER AND TASK TABLES SETUP.
  1378. * REMAINTTI - NUMBER OF INPUT QUEUE BUFFERS LEFT.
  1379. * TTIBITS - ALLOCATION BITMASK FOR INPUT BUFFERS.
  1380. * TTIBUFADDR[ALL] - WHERE THE INPUT BUFFERS ARE.
  1381. * TTIBUFLNK[ALL] - EXISTING LINKAGES OF GROUPED BUFFERS.
  1382. * LOGGEDIN - NUMBER OF USERS IN SMFEX.
  1383. * MAXLOGGED - HIGH WATER MARK OF LOGGEDIN.
  1384. * SWAP QUEUE - SETUP.
  1385. *
  1386. * EXIT SSCINP[-1] - CLEARED.
  1387. * SSCINP[0] - CLEARED UNLESS REMAINTTI WAS ZERO WITH
  1388. * A COMMAND MESSAGE AWAITING QUEUING.
  1389. * LOGGEDIN - INCREMENTED IF CONNECTION MESSAGE.
  1390. * MAXLOGGED - HIGH WATER MARK.
  1391. * REMAINTTI - DECREMENTED IF COMMAND MESSAGE ARRIVED
  1392. * AND REMAINTTI WAS NOT ALREADY ZERO.
  1393. * SWAP QUEUE - UPDATED AS NEEDED.
  1394. * TERMINAL INPUT BUFFERS - IF ALLOCATED, THEN LINKED TO
  1395. * USER TABLE ENTRY OR TO EXISTING BUFFERS.
  1396. * USER TABLE ENTRY - UPDATED AS NEEDED.
  1397. * MEM[0] - SENSE SWITCH 6 SET AS NEEDED.
  1398. * ENABLEFLAG - FORCED NEGATIVE IF NEARING FULL TABLE.
  1399. *
  1400. * CALLS MELT, INSTRMNT2, INSTRMNT1, ALLOC, MOVEWD,
  1401. * SCHEDULE, PURGETTI, SYSTEM, RECALL, GETUSER, PUTINQ,
  1402. * PUTUSER, MAX.
  1403. *
  1404. * USES IAFHEADER, CURUSER.
  1405. #
  1406. ITEM TMP1,TMP2,TMP3;
  1407.  
  1408. SWITCH RCVFNCSW RCVINIT,RCVMSGIN,RCVOUTDONE,RCVBREAK,
  1409. RCVHUNGUP,RCVCONNECT;
  1410. ARRAY VALIDATE[0:5]; ITEM VLDTUSR B=[FALSE,4(TRUE),FALSE];
  1411. ARRAY REJECTION [0:1]; ITEM REJECTMSG;
  1412. ITEM EJT;
  1413.  
  1414. IF SSCINP[-1] NQ 0 THEN
  1415. BEGIN
  1416. STOPNOW=TRUE;
  1417. SSCINP[-1]=0;
  1418. ONSW(O"40"); # SIGNAL SUBSYSTEM TERMINATION #
  1419. END
  1420.  
  1421. IF SHUTDOWN GR 1 THEN RETURN;
  1422.  
  1423. IAFHEADER=SSCINP[0];
  1424. IF IAFHEADER NQ 0 THEN # WE HAVE RECEIVED SOMETHING #
  1425. BEGIN
  1426. IF VLDTUSR[IAFFUNC] THEN
  1427. BEGIN
  1428. CURUSER=0;
  1429. # SEARCH FOR USER AMONG RECENT TASK ASSIGNMENTS #
  1430. FOR TMP1=1 STEP 1 UNTIL TASKSAVAIL DO
  1431. BEGIN
  1432. IF TASKUSER[TMP1] NQ 0 AND USERIAFNUM[TASKUSER[TMP1]]
  1433. EQ IAFTERM THEN
  1434. BEGIN
  1435. CURUSER=TASKUSER[TMP1];
  1436. GOTO RCVFOUND;
  1437. END
  1438. END
  1439. # SEARCH FOR USER BY BRUTE FORCE #
  1440. FOR TMP1=1 STEP 1 UNTIL NUMSMFUSR DO
  1441. BEGIN
  1442. IF USERIAFNUM[TMP1] EQ IAFTERM THEN
  1443. BEGIN
  1444. CURUSER=TMP1;
  1445. GOTO RCVFOUND;
  1446. END
  1447. END
  1448. RCVFOUND:
  1449. IF CURUSER LQ 0 OR CURUSER GR NUMSMFUSR THEN
  1450. BEGIN
  1451. SSCINP[0]=0;
  1452. GOTO AFTERRCV;
  1453. END
  1454. GETUSER;
  1455. END
  1456. GOTO RCVFNCSW[IAFFUNC];
  1457.  
  1458. RCVMSGIN:
  1459. CONTROL IFEQ TRACEFLAG,1;
  1460. P&lt;MOVFROM>=LOC(SSCINP[1]);
  1461. TMP1=IAFLEN-1;
  1462. CONTROL FI;
  1463. TRCBOTH("MSGIN$",CURUSER);
  1464. TRCWORDS(MOVFROM,TMP1);
  1465. CONTROL IFGQ PARANOIA,2;
  1466. IF NOT CURUSLOGGED THEN MELT("DOIN 2$");
  1467. IF IAFLEN GR SIZTTIBUF+1 THEN MELT("DOIN 22$");
  1468. CONTROL FI;
  1469. IF IAFLEN LS 2 THEN
  1470. BEGIN
  1471. SSCINP[0]=0;
  1472. GOTO AFTERRCV;
  1473. END
  1474. CONTROL IFEQ METERING,1;
  1475. INSTRMNT2(INSTST"INPUT",IAFLEN);
  1476. CONTROL FI;
  1477. IF REMAINTTI LQ 0 THEN # TRY ANOTHER DAY #
  1478. BEGIN
  1479. CONTROL IFEQ METERING,1;
  1480. INSTRMNT1(INSTST"NOTTI");
  1481. CONTROL FI;
  1482. GOTO PASTRCV;
  1483. END
  1484. ALLOC(TTIBITS,TTIGOOD,TMP2,NUMTTIBIT);
  1485. CONTROL IFGQ PARANOIA,2;
  1486. IF TMP2 EQ 0 THEN MELT("DOIN 4$"); # MUST SUCCEED #
  1487. CONTROL FI;
  1488. REMAINTTI=REMAINTTI-1; # KEEP TRACK RESOURCE #
  1489. P&lt;MOVFROM>=LOC(SSCINP[1]);
  1490. P&lt;MOVTO>=TTIBUFADDR[TMP2];
  1491. TMP3=IAFLEN-1;
  1492. MOVEWD(TMP3,MOVFROM,MOVTO);
  1493. TTIBUFLEN[TMP2]=TMP3;
  1494. TTIBUFLNK[TMP2]=0;
  1495. IF CURUSTTIBUF EQ 0 THEN # START NEW CHAIN #
  1496. BEGIN
  1497. CURUSTTIBUF=TMP2;
  1498. CONTROL IFEQ METERING,1;
  1499. TMP1=TIMEOFDAY-CURUSLASTIM;
  1500. INSTRMNT2(INSTST"THNK",TMP1);
  1501. CONTROL FI;
  1502. END
  1503. ELSE # ADD TO CHAIN #
  1504. BEGIN
  1505. TMP1=CURUSTTIBUF;
  1506. WHYLE TMP1 NQ 0 DO
  1507. BEGIN
  1508. TMP3=TMP1;
  1509. TMP1=TTIBUFLNK[TMP1];
  1510. END
  1511. TTIBUFLNK[TMP3]=TMP2;
  1512. END
  1513. SCHEDULE;
  1514. GOTO ENDRCV;
  1515.  
  1516. RCVBREAK:
  1517. TRCBOTH("BREAK$",CURUSER);
  1518. CONTROL IFEQ METERING,1;
  1519. INSTRMNT1(INSTST"BREAKS");
  1520. CONTROL FI;
  1521. IF NOT CURUSLOGGED THEN GOTO ENDRCV;
  1522. CURUSINTRPT=TRUE;
  1523. CURUSCRUNCH=FALSE; # IMPROVE SCHEDULEING PRIORITY #
  1524. PURGETTI;
  1525. SCHEDULE;
  1526. GOTO ENDRCV;
  1527.  
  1528. RCVHUNGUP:
  1529. TRCBOTH("HUNGUP$",CURUSER);
  1530. CONTROL IFEQ METERING,1;
  1531. INSTRMNT1(INSTST"HANGUPS");
  1532. CONTROL FI;
  1533. CURUSDROP=TRUE;
  1534. CURUSRCVRY=TRUE;
  1535. GOTO RCVBREAK;
  1536.  
  1537. RCVINIT:
  1538. STOPNOW=TRUE;
  1539. GOTO AFTERRCV;
  1540.  
  1541. RCVOUTDONE: # TTY OUTPUT COMPLETE #
  1542. TRCBOTH("TOCIN $",CURUSER);
  1543. CONTROL IFGQ PARANOIA,3;
  1544. IF NOT CURUSLOGGED THEN MELT("DOIN 43$");
  1545. CONTROL FI;
  1546. SCHEDULE;
  1547. GOTO ENDRCV;
  1548.  
  1549. RCVCONNECT:
  1550. TRCBOTH("CONNECT$",IAFTERM);
  1551. IF IAFTERM GR MAXCONNECT THEN MELT("TABLE LIMIT$");
  1552. CURUSER=0;
  1553. FOR TMP1=1 STEP 1 UNTIL NUMSMFUSR DO
  1554. BEGIN
  1555. IF USERIAFNUM[TMP1] EQ IAFTERM THEN CURUSER=TMP1;
  1556. IF CURUSER EQ 0 THEN
  1557. BEGIN
  1558. IF NOT USERLOGGED[TMP1] THEN CURUSER=TMP1;
  1559. END
  1560. END
  1561. TRCBOTH("PICK USER$",CURUSER);
  1562. IF CURUSER EQ 0 THEN
  1563. BEGIN
  1564. # CRITICAL TABLE SPACE SHORTAGE - SEND LOGOUT FUNCTION TO #
  1565. # IAF IMMEDIATELY AND SERIALIZE UNTIL THIS IS ACCOMPLISHED #
  1566. EJT=B&lt;48,12>SSCINP[1];
  1567. TRYREJECT:
  1568. IAFFUNC=SMF2IAF"LOGOUT";
  1569. IAFLEN=1;
  1570. IAFPTR=0;
  1571. REJECTMSG[0]=0;
  1572. REJECTMSG[1]=IAFHEADER;
  1573. P&lt;SSCBUFFER>=LOC(REJECTION);
  1574. SSCTYPE=O"3";
  1575. SSCCOUNT=1;
  1576. SYSREQ("SSC",0,LOC(SSCBUFFER),IAFSSID);
  1577. IF SSCSTATUS LAN O"7776" EQ 4 THEN
  1578. BEGIN
  1579. RECALL(0);
  1580. GOTO TRYREJECT;
  1581. END
  1582. EESET((TTEQ*4096)+EJT);
  1583. GOTO AFTERRCV;
  1584. END
  1585. USERFLAGS[CURUSER]=0;
  1586. GETUSER;
  1587. CURUSLOGGED=TRUE;
  1588. CURUSSTART=TRUE;
  1589. CURUSIAFNUM=IAFTERM;
  1590. USERJSN[CURUSER]=C&lt;0,4>SSCINP[1];
  1591. USEREJT[CURUSER]=B&lt;48,12>SSCINP[1];
  1592. LOGGEDIN=LOGGEDIN+1;
  1593. IF LOGGEDIN GQ NUMSMFUSR-2 THEN ENABLEFLAG=-1;
  1594. CONTROL IFEQ METERING,1;
  1595. MAXLOGGED=MAX(MAXLOGGED,LOGGEDIN);
  1596. CONTROL FI;
  1597. PUTINQ;
  1598. GOTO ENDRCV;
  1599.  
  1600. ENDRCV:
  1601. CURUSLASTIM=TIMEOFDAY;
  1602. SSCINP[0]=0;
  1603. PASTRCV:
  1604. PUTUSER;
  1605. AFTERRCV:
  1606.  
  1607. END # OF BUFFER0 HANDLER #
  1608.  
  1609. END # OF DOINPUT #
  1610. PAGE # RUNJOBS -- TRY TO DO SOME USER CODE #
  1611.  
  1612.  
  1613.  
  1614. PROC RUNJOBS;
  1615. BEGIN
  1616. #
  1617. ** RUNJOBS - SUPERVISE TASK EXECUTION.
  1618. *
  1619. * RUNJOBS CONTROLS TASK EXECUTION. TASKS GET THE CPU ONLY
  1620. * FROM RUNJOBS, AND ARE REQUIRED TO EXIT EACH TIME SLICE TO
  1621. * THE APPROPRIATE LABEL WITHIN RUNJOBS. SINCE RUNJOBS IS THE
  1622. * SOLE PATH FOR TASKS TO RECEIVE CONTROL, IT IS NOT NECESSARY
  1623. * FOR RUNJOBS ITSELF TO USE REENTRANT ENTRY AND EXIT EVEN
  1624. * THOUGH ITS SUBROUTINES ARE THEMSELVES REENTRANT.
  1625. *
  1626. * NOTE THAT THERE IS NO ARCHITECTURAL PROTECTION AGAINST
  1627. * RENEGADE TASKS. IF A TASK LOOPS OR OVERWRITES MEMORY, THE
  1628. * ENTIRE SUBSYSTEM WILL BE IMPACTED. THEREFORE, MULTI-USER
  1629. * EDITING CODE MUST BE BUG-FREE. EDITING CODE MUST ALSO BE
  1630. * SENSITIVE AND REASONABLE IN RESOURCE CONSUMPTION SINCE THIS
  1631. * SUBSYSTEM EXECUTES AT A VERY HIGH PRIORITY.
  1632. *
  1633. * RUNJOBS PERFORMS TWO PRELIMINARY PHASES BEFORE INITIATING
  1634. * TASKS. THE FIRST PRELIMINARY PHASE ACCOUNTS FOR THE LEVEL
  1635. * OF UTILIZATION, BOTH FOR STATISTICAL REASONS AND TO ENABLE
  1636. * SCHEDULING RULES TO "TRY HARDER". THE SECOND PRELIMINARY
  1637. * PHASE CHECKS FOR SHUTDOWN CONDITIONS.
  1638. *
  1639. * THE PRINCIPAL FUNCTION OF RUNJOBS IS TO ADVANCE THE STATUS
  1640. * OF EACH AVAILABLE TASK. WHILE THE SUBSYSTEM IS COMPILED
  1641. * WITH A LARGE NUMBER OF TASKS IN EXISTENCE, THE NUMBER OF
  1642. * TASKS AVAILABLE FOR EXECUTION IS DETERMINED AT SUBSYSTEM
  1643. * STARTUP AND IS TYPICALLY MUCH SMALLER.
  1644. *
  1645. * EACH TASK CAN HAVE ANY OF THE FOLLOWING STATUSES --
  1646. *
  1647. * 1. IT MAY BE EMPTY. AN EMPTY TASK WILL BE ASSIGNED TO A
  1648. * USER IF THERE ARE USERS IN THE SCHEDULING (SWAPIN) QUEUE
  1649. * AND NO SHUTDOWN CONDITION EXISTS. IN ASSIGNING A USER TO A
  1650. * PREVIOUSLY EMPTY TASK, THE TASK STATUS IS CHANGED TO
  1651. * "START" OR "SWAPIN" BASED ON THE USER'S PROGRESS.
  1652. *
  1653. * 2. IT MAY BE DELAYING. A DELAYING TASK MISSES THE CPU FOR
  1654. * PRECISELY ONE SMFEX CPU RECALL CYCLE, AND TYPICALLY IS
  1655. * WASTING REAL TIME WHILE POLLING ON COMPLETION OF AN I/O
  1656. * FUNCTION. IN VIEW OF THE BRUTE FORCE REQUIRED TO RESTART A
  1657. * DELAYED TASK, THIS STYLE OF WAITING FOR I/O IS NOT USED
  1658. * OFTEN WITHIN THE EDITING CODE, BUT IT IS FULLY SUPPORTED BY
  1659. * THIS EXECUTIVE. RUNJOBS RESTARTS A DELAYED TASK AS SOON AS
  1660. * IT IS DISCOVERED, BY CHANGING THE TASK STATUS TO "RUN".
  1661. *
  1662. * 3. A TASK MAY BE IN AUTO RECALL. THIS TASK WISHES TO MISS
  1663. * THE CPU UNTIL SMFEX DETECTS THAT THE SPECIFIED COMPLETION
  1664. * BIT HAS BEEN TOGGLED BY ANYBODY. THIS IS THE METHOD
  1665. * GENERALLY USED WITHIN THE EDITOR TO WAIT FOR I/O, SINCE IT
  1666. * AVOIDS WASTING CPU TIME TO START UP A DELAYED TASK WHICH IS
  1667. * LIKELY TO DROP RIGHT BACK INTO DELAY. ONCE SMFEX VERIFIES
  1668. * THAT THE DESIRED EVENT IS COMPLETE, IT RESTARTS A RECALLED
  1669. * TASK BY CHANGING THE TASK STATUS TO "RUN".
  1670. *
  1671. * 4. A TASK MAY BE IN "START" STATUS. THIS TASK IS READY
  1672. * FOR THE CPU, FOR A USER WHO HAS NOT YET EXECUTED ANY
  1673. * MULTI-USER EDITING CODE. THE TASK WILL GET THE CPU AT THE
  1674. * EDITOR'S MAIN ENTRY POINT. NO SWAP PAGE EXISTS YET, AND
  1675. * DISPATCHING DATA IS IN MODEL FORMAT.
  1676. *
  1677. * 5. A TASK MAY BE IN "SWAPIN" STATUS. THIS TASK HAS
  1678. * PREVIOUSLY EXECUTED AND SWAPPED OUT. THE TASK THEREFORE
  1679. * WANTS THE CPU AT THE ENTRY POINT OF THE SWAPPING CODE.
  1680. * SINCE THE SWAPOUT AND SWAPIN CODE ARE ONE AND THE SAME,
  1681. * TASK CPU DISPATCHING IS EFFECTED BY RETURNING TO THE SWAP
  1682. * CODE WHERE CONTROL WAS PREVIOUSLY SURRENDERED. THAT SWAP
  1683. * CODE WILL READ IN THE SWAP CODE AND ALTER THE MEMORY IMAGE
  1684. * FOR THE TASK ON THE FLY, THEN RETURN OUT THE THE EDITING
  1685. * CODE WHICH HAD CAUSED THE PREVIOUS SWAPOUT.
  1686. *
  1687. * 6. A TASK MAY BE IN "RUN" STATUS. THIS TASK HAS BEEN
  1688. * SWAPPED IN FOR SOME TIME, AND IS PRESENTLY COMPLETING A
  1689. * DELAY OR RECALL. SINCE THE MEMORY IMAGE FOR THE TASK IS
  1690. * INTACT, WE ARE REQUIRED ONLY TO MANIPULATE THOSE ARRAYS
  1691. * CRITICAL TO TASK DISPATCHING, AND RETURN TO THE POINT IN
  1692. * THE EDITING CODE WHERE THE TASK HAD PREVIOUSLY PAUSED.
  1693. *
  1694. * EACH TIME A TASK GETS THE CPU, IT CAN FINISH ITS TIME SLICE
  1695. * IT THREE WAYS -- (1) THE ENTIRE EDIT SESSION MAY END, IN
  1696. * WHICH CASE THE TASK EXITS VIA LABEL "AFTEREDIT" FOR CLEANUP
  1697. * PROCESSING, OR (2) THE TASK MAY COMPLETE A TRANSACTION,
  1698. * I.E., IT MAY FINISH SWAPPING OUT FOR TERMINAL I/O OR
  1699. * RESOURCE BALANCING, IN WHICH CASE IT EXITS VIA LABEL
  1700. * "AFTERTRANS", OR (3) IT MAY NEED TO DELAY/RECALL WITHIN ITS
  1701. * MEMORY IMAGE (I.E., WHILE STILL SWAPPED IN) FOR SOME DISK
  1702. * I/O OR OTHER SHORT-TERM EVENT, IN WHICH CASE IT EXITS VIA
  1703. * LABEL "AFTERSLICE".
  1704. *
  1705. * IN SUMMARY, THERE ARE THREE WAYS FOR A TASK TO BE ASSIGNED
  1706. * THE CPU (START OF SESSION, START OF TRANSACTION, OR RESTART
  1707. * AFTER DELAY) AND THREE WAYS FOR A TASK TO FORFEIT THE CPU
  1708. * (END OF SESSION, END OF TRANSACTION, DELAY), AND THESE
  1709. * ENTRIES AND EXITS CAN BE MIXED IN ANY FASHION. AS A
  1710. * RESULT, RUNJOBS MUST VIOLATE A RULE OF CLEAN PROGRAMMING
  1711. * PRACTISE, IN ALLOWING JUMPS INTO BLOCKS OF CODE (IF-THEN,
  1712. * NOT LOOPS) WHICH ARE NOT NECESSARILY ACTIVE.
  1713. *
  1714. *
  1715. * ENTRY SHUTDOWN - CONTROLS WHETHER TO EXECUTE AT ALL.
  1716. * SWPQHEAD - START OF SWAPIN QUEUE.
  1717. * TASKSAVAIL - NUMBER OF TASKS WE CAN USE.
  1718. * TASK AND USER TABLES - SETUP.
  1719. * MODELPTR, MODELLEN - MODEL FORMAT DISPATCH DATA.
  1720. * TIMEOFDAY - MILLISECOND CLOCK.
  1721. * LOGGEDIN - NUMBER OF USERS.
  1722. *
  1723. * EXIT TASKSBUSY - NUMBER OF NON-EMPTY TASKS.
  1724. * COMPLETE - FORCED TRUE BASED ON SHUTDOWN.
  1725. * LOGGEDIN - DECREMENTED FOR ANY SESSION COMPLETIONS.
  1726. * ENABLEFLAG - NON-ZERO POSITIVE IF LOGGEDIN
  1727. * DECREMENTS OUT OF NEAR-FULL CONDITION.
  1728. * USER AND TASK TABLES - UPDATED AS NEEDED.
  1729. *
  1730. * CALLS INSTRMNT1, GETUSER, TAKEOFFQ, PUTUSER, GETCOMMON,
  1731. * MOVEWD, GENWRKNAM, EDTINIT, PROCESS, EDTTERM,
  1732. * MELT, ABTKILL, ABTPAUSE, RTRNWRKFIL, SENDLOGOUT,
  1733. * KILL, TRANSACT, PUTINQ, SPREAD, GATHER.
  1734. *
  1735. * USES CURUSER, CURTASK, RSTKPTR, RENTSTK.
  1736. *
  1737. * NOTE WHENEVER RUNJOBS INVOKES A TASK, BY CALLING
  1738. * PROCESS, TRANSACT, OR RESUME, THE FOLLOWING
  1739. * CONVENTIONS APPLY FOR PARAMETERS PASSED TO AND
  1740. * FROM THE EDITOR CODE --
  1741. *
  1742. * PASSED CURTASK, CURUSER, RSTKPTR, RENTSTK,
  1743. * WORKNAM, P<MANY ARRAYS>.
  1744. *
  1745. * RETURNED ABORTED, RSTKPTR, RENTSTK,
  1746. * CHNGSTATUS, TASKRCLADR[CURTASK].
  1747. #
  1748. ITEM TMP1,TMP2;
  1749. XDEF LABEL AFTEREDIT;
  1750. XDEF LABEL AFTERTRANS;
  1751. XDEF LABEL AFTERSLICE;
  1752. XREF LABEL RESUME;
  1753.  
  1754. TASKSBUSY=0; # COUNT UP TASK UTILIZATION #
  1755. FOR TMP1=1 STEP 1 UNTIL NUMTASKS DO IF TASKSTATUS[TMP1] NQ
  1756. TASKST"EMPTY" THEN TASKSBUSY=TASKSBUSY+1;
  1757. CONTROL IFEQ METERING,1;
  1758. IF TASKSBUSY GQ TASKSAVAIL AND SWPQHEAD NQ 0
  1759. THEN INSTRMNT1(INSTST"NOTASK");
  1760. CONTROL FI;
  1761.  
  1762. IF SHUTDOWN GR 1 THEN # SEE IF SINUSES CLEARED #
  1763. BEGIN
  1764. IF TASKSBUSY EQ 0 THEN # ALL ACTIVITY CEASED #
  1765. BEGIN
  1766. IF (SHUTDOWN GQ 2 AND SWPQHEAD EQ 0) OR
  1767. SHUTDOWN EQ 4 THEN COMPLETE=TRUE;
  1768. END
  1769. END
  1770. IF SHUTDOWN EQ 1 AND LOGGEDIN EQ 0 THEN COMPLETE=TRUE;
  1771.  
  1772.  
  1773. FOR CURTASK=1 STEP 1 UNTIL TASKSAVAIL DO
  1774. BEGIN
  1775.  
  1776. IF SWPQHEAD NQ 0 AND SHUTDOWN LQ 3
  1777. AND TASKSTATUS[CURTASK] EQ TASKST"EMPTY" THEN
  1778. BEGIN
  1779. CURUSER=SWPQHEAD;
  1780. WHYLE CURUSER NQ 0 AND USERTTIBUF[CURUSER] EQ 0
  1781. DO CURUSER=USERQUELNK[CURUSER];
  1782. IF CURUSER EQ 0 THEN
  1783. BEGIN
  1784. CURUSER=SWPQHEAD;
  1785. WHYLE CURUSER NQ 0 AND USERCRUNCH[CURUSER]
  1786. DO CURUSER=USERQUELNK[CURUSER];
  1787. IF CURUSER EQ 0 THEN CURUSER=SWPQHEAD;
  1788. END
  1789. TRCBOTH("ASGN SLT$",CURTASK); TRCDEC(CURUSER);
  1790. GETUSER;
  1791. CURUSCRUNCH=FALSE;
  1792. CURUSINTASK=TRUE;
  1793. CURUSTASK=CURTASK;
  1794. TAKEOFFQ;
  1795. TASKUSER[CURTASK]=CURUSER;
  1796. TASKFLAGS[CURTASK]=0; # CLEAR ALL #
  1797. TASKNXTTTO[CURTASK]=0;
  1798. TASKTYPTTO[CURTASK]=0;
  1799. IF CURUSSTART THEN TASKSTATUS[CURTASK]=TASKST"START";
  1800. ELSE TASKSTATUS[CURTASK]=TASKST"SWAP";
  1801. PUTUSER;
  1802. END
  1803.  
  1804. IF TASKSTATUS[CURTASK] EQ TASKST"EMPTY" THEN TEST CURTASK;
  1805.  
  1806. IF TASKSTATUS[CURTASK] EQ TASKST"DELAY" THEN
  1807. BEGIN
  1808. TASKSTATUS[CURTASK]=TASKST"RUN";
  1809. END
  1810.  
  1811. IF TASKSTATUS[CURTASK] EQ TASKST"RECALLFET" THEN
  1812. BEGIN
  1813. IF B&lt;59,1>MEM[TASKRCLADR[CURTASK]] EQ 1 THEN
  1814. BEGIN
  1815. TASKSTATUS[CURTASK]=TASKST"RUN";
  1816. END
  1817. END
  1818.  
  1819. IF TASKSTATUS[CURTASK] EQ TASKST"START" THEN
  1820. BEGIN
  1821. CURUSER=TASKUSER[CURTASK];
  1822. TRCBOTH("TASK STRT$",CURTASK); TRCDEC(CURUSER);
  1823. GETUSER;
  1824. CONTROL IFEQ METERING,1;
  1825. INSTRMNT1(INSTST"SESSION");
  1826. CONTROL FI;
  1827. CURUSSTART=FALSE;
  1828. RSTKPTR=1; # MAKE A NEW STACK #
  1829. GETCOMMON; # SET ARRAY BASES #
  1830. P&lt;MOVFROM>=MODELPTR;
  1831. MOVEWD(MODELLEN,MOVFROM,DATAEND); # VIRGIN EDIT DATA #
  1832. GENWRKNAM;
  1833. TASKTIME[CURTASK]=TIMEOFDAY; # SINCE NO SWAPIN #
  1834. IF NOT CURUSRCVRY THEN
  1835. BEGIN
  1836. EDTINIT;
  1837. PROCESS;
  1838. EDTTERM;
  1839. END
  1840. AFTEREDIT: # CONTROL FORCE HERE IF RCVRY #
  1841. CONTROL IFEQ METERING,1;
  1842. INSTRMNT1(INSTST"ENDEDT");
  1843. CONTROL FI;
  1844. CURUSDONE=TRUE;
  1845. CONTROL IFEQ TRACEFLAG,1;
  1846. IF ABORTED THEN TRACESTR("ABORTEDIT$");
  1847. ELSE TRACESTR("ENDEDIT$");
  1848. CONTROL FI;
  1849. CONTROL IFEQ MELTONABT,1;
  1850. IF ABORTED THEN MELT("SUBTASK ABORT$");
  1851. CONTROL FI;
  1852. RSTKPTR=1;
  1853. IF ABORTED THEN
  1854. BEGIN
  1855. IF TASKABORT[CURTASK] THEN ABTKILL;
  1856. ELSE
  1857. BEGIN
  1858. TASKABORT[CURTASK]=TRUE;
  1859. ABTPAUSE;
  1860. TASKABORT[CURTASK]=FALSE;
  1861. END
  1862. END
  1863. RTRNWRKFIL; # RETURN THE WORK FILE #
  1864. SENDLOGOUT; # TRANSMIT LOGOUT FUNCTION #
  1865. LOGGEDIN=LOGGEDIN-1;
  1866. IF LOGGEDIN EQ NUMSMFUSR-5 THEN ENABLEFLAG=1;
  1867. TASKSTATUS[CURTASK]=TASKST"EMPTY";
  1868. LASTTASK=0;
  1869. KILL;
  1870. END
  1871.  
  1872. IF TASKSTATUS[CURTASK] EQ TASKST"SWAP" THEN
  1873. BEGIN
  1874. CURUSER=TASKUSER[CURTASK];
  1875. TRCBOTH("TASK TRNS$",CURTASK); TRCDEC(CURUSER);
  1876. GETUSER;
  1877. RSTKPTR=CURUSSTKPTR ; # HE REMEMBERS HIS PLACE #
  1878. GETCOMMON;
  1879. FETFNT=CURUSFNTPTR;
  1880. GENWRKNAM;
  1881. TRANSACT; # RUNS AS SUBROUTINE OF USER #
  1882. AFTERTRANS: # CONTROL COMES HERE MANUALLY FROM TRANSACT/ENDTRANS #
  1883. CURUSSTKPTR=RSTKPTR;
  1884. CURUSFNTPTR=FETFNT;
  1885. CURUSINTASK=FALSE;
  1886. IF TASKREQUE[CURTASK] THEN PUTINQ;
  1887. TASKSTATUS[CURTASK]=TASKST"EMPTY";
  1888. LASTTASK=0;
  1889. PUTUSER;
  1890. END
  1891.  
  1892. IF TASKSTATUS[CURTASK] EQ TASKST"RUN" THEN
  1893. BEGIN
  1894. CURUSER=TASKUSER[CURTASK];
  1895. TRCBOTH("TASK RUN$",CURTASK); TRCDEC(CURUSER);
  1896. GETUSER;
  1897. IF SHUTDOWN EQ 4 THEN # SELF DESTRUCT #
  1898. BEGIN
  1899. TASKSTATUS[CURTASK]=TASKST"EMPTY";
  1900. RETURN;
  1901. END
  1902. RSTKPTR=TASKSTKPTR[CURTASK]; # HE REMEMBERS PLACE #
  1903. GETCOMMON;
  1904. MOVEWD(RSTKPTR-1,DISPRSTK,RENTSTK);
  1905. SPREAD(RSTKPTR,RENTSTK);
  1906. IF CURUSINTRPT THEN USRBRK=1;
  1907. IF SHUTDOWN GR 2 THEN
  1908. BEGIN
  1909. USRBRK=1;
  1910. FORCENULL=TRUE;
  1911. END
  1912. GENWRKNAM;
  1913. GOTO RESUME; # TO RESUME JOB WHERE IT WAS #
  1914. AFTERSLICE: # CONTROL MANUALLY SENT HERE BY PAUSE #
  1915. GATHER(RSTKPTR,RENTSTK); # SAVE ALL SUBROUTINES #
  1916. MOVEWD(RSTKPTR-1,RENTSTK,DISPRSTK);
  1917. TASKSTATUS[CURTASK]=CHNGSTATUS;
  1918. TASKSTKPTR[CURTASK]=RSTKPTR;
  1919. PUTUSER;
  1920. END
  1921.  
  1922. END # OF POLLING LOOP #
  1923.  
  1924.  
  1925. END # OF RUNJOBS #
  1926. PAGE # INSTRUMENT -- COLLECT STATS #
  1927.  
  1928.  
  1929. CONTROL IFEQ METERING,1;
  1930. PROC INSTRUMENT(TYPE,DATA,DATA2);
  1931. BEGIN
  1932. #
  1933. ** INSTRUMENT - TAKE STATISTICS.
  1934. *
  1935. * INSTRUMENT, TOGETHER WITH ENTRY POINTS INSTRMNT1,
  1936. * INSTRMNT2, AND INSTRMNT3, COLLECTS STATISTICS REGARDING
  1937. * INTERNAL PERFORMANCE AND WORKLOAD CHARACTERISTICS.
  1938. *
  1939. * ENTRY TYPE - SELECTS STATISTICAL CASE.
  1940. * DATA - ONE DATA ITEM, WHERE APPLICABLE.
  1941. * DATA2 - ADDITIONAL DATA WHERE REQUIRED.
  1942. * MAXLOGGED, LOGGEDIN, TIMEOFDAY, SLICECOUNT,
  1943. * BUILDCIO, ACCTTRANS, PALAST[0] - ADDITIONAL
  1944. * PARAMETERS FOR CERTAIN FUNCTION TYPES.
  1945. *
  1946. * EXIT STATWORD[ALL] - INCREMENTED OR SET.
  1947. * DISTRSTM, DISTTKTM, DISTCICT, DISTTRCT, DISTFLSZ,
  1948. * DISTMGSZ - FREQUENCY DISTRIBUTIONS.
  1949. *
  1950. * CALLS ADDVECT.
  1951. #
  1952. ITEM DATA,DATA2,TYPE;
  1953.  
  1954. ENTRY PROC INSTRMNT1(TYPE);
  1955.  
  1956. ENTRY PROC INSTRMNT2(TYPE,DATA);
  1957.  
  1958. ENTRY PROC INSTRMNT3(TYPE,DATA,DATA2);
  1959.  
  1960. SWITCH INSTSW INSTTHNK,INSTRSPNS,INSTNOTTI,
  1961. INSTNOTASK,INSTSWPE,INSTSWPD,INSTCLOCK,
  1962. INSTPREEMPT,INSTSWPTIM,INSTEDTCIO,
  1963. INSTSESSION,INSTTRANS,INSTXSTTO,
  1964. INSTBREAK,INSTHANG,INSTBGNEDT,
  1965. INSTENDEDT,INSTINPUT,INSTXMIT,
  1966. INSTKWIK,INSTUTIL,INSTWORK,INSTDROP;
  1967.  
  1968. GOTO INSTSW[TYPE];
  1969.  
  1970. INSTNOTTI:
  1971. STATWORD[1]=STATWORD[1]+1;
  1972. RETURN;
  1973.  
  1974. INSTNOTASK:
  1975. STATWORD[2]=STATWORD[2]+1;
  1976. RETURN;
  1977.  
  1978. INSTSESSION:
  1979. STATWORD[3]=STATWORD[3]+1;
  1980. RETURN;
  1981.  
  1982. INSTTRANS:
  1983. STATWORD[4]=STATWORD[4]+1;
  1984. RETURN;
  1985.  
  1986. INSTRSPNS:
  1987. STATWORD[5]=STATWORD[5]+DATA;
  1988. ADDVECT(DISTRSTM,DATA/16);
  1989. RETURN;
  1990.  
  1991. INSTTHNK:
  1992. STATWORD[6]=STATWORD[6]+DATA;
  1993. ADDVECT(DISTTKTM,DATA/1024);
  1994. RETURN;
  1995.  
  1996. INSTPREEMPT: # WORDS 7, 8, 9 #
  1997. STATWORD[6+DATA]=STATWORD[6+DATA]+1;
  1998. RETURN;
  1999.  
  2000. INSTXSTTO:
  2001. STATWORD[10]=STATWORD[10]+1;
  2002. RETURN;
  2003.  
  2004. INSTBREAK:
  2005. STATWORD[11]=STATWORD[11]+1;
  2006. RETURN;
  2007.  
  2008. INSTHANG:
  2009. STATWORD[12]=STATWORD[12]+1;
  2010. RETURN;
  2011.  
  2012. INSTCLOCK:
  2013. STATWORD[13]=MAXLOGGED;
  2014. STATWORD[14]=LOGGEDIN;
  2015. STATWORD[15]=TIMEOFDAY;
  2016. STATWORD[16]=SLICECOUNT;
  2017. RETURN;
  2018.  
  2019. INSTSWPE:
  2020. STATWORD[17]=STATWORD[17]+1;
  2021. RETURN;
  2022.  
  2023. INSTSWPD:
  2024. STATWORD[18]=STATWORD[18]+1;
  2025. RETURN;
  2026.  
  2027. INSTSWPTIM:
  2028. STATWORD[19]=STATWORD[19]+DATA;
  2029. RETURN;
  2030.  
  2031. INSTEDTCIO:
  2032. STATWORD[20]=STATWORD[20]+DATA; # CIO MSECS #
  2033. STATWORD[21]=STATWORD[21]+DATA2; # CIO COUNT #
  2034. IF DATA2 EQ 0 THEN STATWORD[22]=STATWORD[22]+1; # NUM ZERO CIO #
  2035. IF DATA2 GQ 16 THEN
  2036. BEGIN
  2037. STATWORD[23]=STATWORD[23]+1; # NUM CRUNCHERS #
  2038. STATWORD[24]=STATWORD[24]+DATA2; # CRUNCHY EFFORT #
  2039. END
  2040. ADDVECT(DISTCICT,DATA2);
  2041. RETURN;
  2042.  
  2043. INSTBGNEDT:
  2044. STATWORD[25]=STATWORD[25]+BUILDCIO; # FILEBUILD CIOS #
  2045. RETURN;
  2046.  
  2047. INSTENDEDT:
  2048. ADDVECT(DISTTRCT,ACCTTRANS);
  2049. ADDVECT(DISTFLSZ,PALAST[0]);
  2050. RETURN;
  2051.  
  2052. INSTINPUT:
  2053. STATWORD[26]=STATWORD[26]+DATA; # NUM WORDS #
  2054. RETURN;
  2055.  
  2056. INSTXMIT:
  2057. STATWORD[27]=STATWORD[27]+DATA; # NUM WORDS #
  2058. STATWORD[28]=STATWORD[28]+DATA2; # NUM BLOCKS #
  2059. ADDVECT(DISTMGSZ,DATA);
  2060. RETURN;
  2061.  
  2062. INSTKWIK:
  2063. STATWORD[29]=STATWORD[29]+1;
  2064. RETURN;
  2065.  
  2066. INSTUTIL:
  2067. STATWORD[30]=STATWORD[30]+DATA;
  2068. RETURN;
  2069.  
  2070. INSTWORK:
  2071. STATWORD[31+DATA]=STATWORD[31+DATA]+1; # WORDS 31 THRU 41 #
  2072. RETURN;
  2073.  
  2074. INSTDROP:
  2075. STATWORD[42]=STATWORD[42]+1;
  2076. RETURN;
  2077.  
  2078. END # OF INSTRUMENT #
  2079. CONTROL FI;
  2080. PAGE # USER-STATE CODE #
  2081. # BASIC WAIT/INTERRUPT HOOKS #
  2082.  
  2083.  
  2084. PROC SMFDLY;
  2085. IOBEGIN(SMFDLY)
  2086. #
  2087. ** SMFDLY - INTERFACE FOR TASKS TO DELAY.
  2088. *
  2089. * EDITING CODE USE COMPILE-TIME MACROS TO REDEFINE THE
  2090. * KEYWORD "DELAY" INTO A CALL TO "SMFDLY" FOR MULTI-USER
  2091. * CODE. SMFDLY INTERFACES TO THE PAUSE ROUTINE, WHICH IN
  2092. * TURN WORKS WITH RUNJOBS TO CONTROL THE TASK.
  2093. *
  2094. * ENTRY NO CONDITIONS.
  2095. *
  2096. * EXIT AFTER DELAYING.
  2097. *
  2098. * CALLS PAUSE.
  2099. *
  2100. * USES CHNGSTATUS.
  2101. #
  2102. CHNGSTATUS=TASKST"DELAY";
  2103. PAUSE;
  2104. IOEND # OF SMFDLY #
  2105.  
  2106.  
  2107. PROC SMFRCL(AFET);
  2108. IOBEGIN(SMFRCL)
  2109. #
  2110. ** SMFRCL - INTERFACE FOR TASKS TO AUTO-RECALL ON AN EVENT.
  2111. *
  2112. * EDITING CODE USE COMPILE-TIME MACROS TO REDEFINE THE
  2113. * KEYWORD "RECALL" INTO A CALL TO "SMFRCL" FOR MULTI-USER
  2114. * CODE. SMFDLY INTERFACES TO THE PAUSE ROUTINE, WHICH IN
  2115. * TURN WORKS WITH RUNJOBS TO CONTROL THE TASK.
  2116. *
  2117. * NOTE THAT EDITING CODE IS NOT ALLOWED TO SPECIFY AUTO-RECALL
  2118. * ON ANY RA+1 CALL. INSTEAD, EDITING CODE MUST ISSUE
  2119. * RA+1 AND THEN CALL THIS ROUTINE TO RECALL UNTIL THE SYSTEM
  2120. * FUNCTION IS COMPLETE.
  2121. *
  2122. * ENTRY AFET - COMPLETION WORD.
  2123. *
  2124. * EXIT AFTER COMPLETION BIT IS FOUND TO BE ON.
  2125. *
  2126. * CALLS PAUSE.
  2127. *
  2128. * USES CHNGSTATUS, TASKRCLADR[CURTASK].
  2129. #
  2130. ARRAY AFET;;
  2131. TASKRCLADR[CURTASK]=LOC(AFET);
  2132. CHNGSTATUS=TASKST"RECALLFET";
  2133. PAUSE;
  2134. IOEND # OF SMFRCL #
  2135.  
  2136.  
  2137. PROC CLEARINT;
  2138. IOBEGIN(CLEARINT)
  2139. #
  2140. ** CLEARINT - ACKNOWLEGE USER BREAK.
  2141. *
  2142. * EDITING CODE IS REQUIRED TO CALL THIS ROUTINE AS SOON AS
  2143. * A USER BREAK HAS BEEN NOTICED, AND ALL EDITOR-SPECIFIC
  2144. * RESPONSES HAVE BEEN PERFORMED. CLEARINT CLEARS FLAGS
  2145. * INDICATING UNACKNOWLEGED INTERRUPT, SINCE ONLY EXECUTIVE
  2146. * CODE CAN ACCESS SUCH FLAGS.
  2147. *
  2148. * ENTRY NO CONDITIONS.
  2149. *
  2150. * EXIT CURUSINTRPT - FALSE.
  2151. * BUFFERED OUTPUT PURGED.
  2152. * TASKREQUE - FALSE UNLESS TASK RECOVERY IN EFFECT.
  2153. *
  2154. * CALLS CLEARQUE.
  2155. #
  2156. IF CURUSINTRPT THEN TASKNXTTTO[CURTASK]=0;
  2157. CLEARQUE;
  2158. CURUSINTRPT=FALSE;
  2159. IOEND # OF CLEARINT #
  2160.  
  2161.  
  2162. PROC CLEARQUE;
  2163. BEGIN
  2164. #
  2165. ** CLEARQUE - ATTEMPT TO CLEAR TASKREQUE FLAG.
  2166. *
  2167. * CLEARQUE CLEARS THE TASKREQUE FLAG UNLESS TASK RECOVERY IS
  2168. * IN EFFECT. TASKREQUE IS SET BY DOINPUT WHEN A USER NEEDS
  2169. * TO BE SCEDULED TO A TASK BUT IS ALREADY IN A TASK. DOINPUT
  2170. * HAS NO WAY TO KNOW IF THE TASK ALREADY RUNNING WILL DETECT
  2171. * OR IGNORE THE INPUT EVENT. THUS, THE TASKREQUE FLAG IS
  2172. * SET. IF THE EDITING CODE NEVER USES CLEARQUE TO SHOW
  2173. * ACKNOWLEGEMENT, THEN WHEN THE TASK SWAPS OUT THE RUNJOBS
  2174. * ROUTINE WILL IMMEDIATELY PUT THE USER BACK IN THE SWAPIN
  2175. * QUEUE. IF THE EDITING CODE ACKNOWLEGES THE INPUT EVENT,
  2176. * WHICH IS USUALLY A USER BREAK, THEN CLEARQUE GETS RID OF
  2177. * THE RESCHEDULING AT END OF TRANSACTION.
  2178. *
  2179. * THE TASKREQUE FLAG IS PRESERVED IF RECOVERY IS ON.
  2180. * RECOVERY DEALS WITH JOB DETACHMENT AND SUBSYSTEM EXITS.
  2181. *
  2182. * ENTRY CURUSRCVRY - WHETHER RECOVERY IN EFFECT.
  2183. * TASKREQUE[CURTASK] - WHETHER RESCHEDULING PLANNED.
  2184. *
  2185. * EXIT TASKREQUE[CURTASK] - UPDATED.
  2186. #
  2187. TASKREQUE[CURTASK]=TASKREQUE[CURTASK] AND CURUSRCVRY;
  2188. END # OF CLEARQUE #
  2189.  
  2190.  
  2191. PROC SPINWHEELS;
  2192. IOBEGIN(SPINWHEELS)
  2193. #
  2194. ** SPINWHEELS - DELAY TASK UNTIL INPUT ARRIVES.
  2195. *
  2196. * SPINWHEELS ALLOWS A TASK TO HOLD ONTO ITS RESOURCES FOR
  2197. * BRIEF TIME INTERVALS IN EXPECTATION OF A USEFUL EXTERNAL
  2198. * ARRIVING PROBABLY WITHIN A FRACTION OF A SECOND. IF
  2199. * RESOURCES ARE TIGHT WE TERMINATE THE WAIT SO THE CALLER CAN
  2200. * SWAP OUT.
  2201. *
  2202. * ENTRY TIMEOFDAY - CURRENT TIME.
  2203. * TASKREQUE[CURTASK], TASKTIME[CURTASK], REMAINTTI,
  2204. * TASKAVAIL, TASKSBUSY - EVENT/RESOURCE DATA.
  2205. * SPINTIME - TIME ALREADY SPENT SPINNING.
  2206. *
  2207. * EXIT TIMEOFDAY - CURRENT TIME MAY HAVE ADVANCED.
  2208. * SPINTIME - POSSIBLY INCREMENTED.
  2209. *
  2210. * CALLS OKTOWAIT(INTERNAL), SMFRCL.
  2211. *
  2212. * USES SPINSTART, TASKPULSE[CURTASK].
  2213. #
  2214.  
  2215. FUNC OKTOWAIT B;
  2216. BEGIN
  2217. #
  2218. ** OKTOWAIT - COMPUTE RULES FOR SPINWHEELS.
  2219. *
  2220. * OKTOWAIT DETERMINES THE EVENT/RESOURCE THRESHOLDS FOR THE
  2221. * SPINWHEELS ROUTINES. A TASK MAY SPIN ITS WHEELS, HOLDING
  2222. * RESOURCES, UNTIL/UNLESS ANY OF THE FOLLOWING --
  2223. *
  2224. * 1. THE DESIRED INPUT ARRIVES FROM IAFEX (TASKREQUE)
  2225. *
  2226. * 2. TWO SECONDS EXPIRE.
  2227. *
  2228. * 3. ONE-HALF SECOND EXPIRES AND THERE ARE MORE USERS
  2229. * SCHEDULED FOR TASKS THAN TASKS LEFT TO TAKE THEM.
  2230. *
  2231. * 4. REGARDLESS OF TIMING, LESS THAN HALF OF THE TERMINAL
  2232. * INPUT BUFFERS ARE LEFT OVER. (MOST CRITICAL RESOURCE)
  2233. *
  2234. * ENTRY AND EXIT - SEE OUTER PROCEDURE.
  2235. #
  2236. OKTOWAIT=TRUE;
  2237. IF TASKREQUE[CURTASK] OR TIMEOFDAY-TASKTIME[CURTASK]
  2238. GR 2000 THEN OKTOWAIT=FALSE;
  2239. IF NUMTTIBUF-REMAINTTI GR TASKSAVAIL-TASKSBUSY AND
  2240. TIMEOFDAY-TASKTIME[CURTASK] GR 500 THEN OKTOWAIT=FALSE;
  2241. IF REMAINTTI LQ NUMTTIBUF/2 THEN OKTOWAIT=FALSE;
  2242. END
  2243.  
  2244.  
  2245. # SPINWHEELS MAIN CODE STARTS HERE #
  2246.  
  2247. SPINSTART=TIMEOFDAY;
  2248. WHYLE OKTOWAIT DO
  2249. BEGIN
  2250. TASKPULSE[CURTASK]=2; # SIMULATE BUSY FET #
  2251. P&lt;MOVTO>=LOC(TASKPULSE[CURTASK]);
  2252. SMFRCL(MOVTO); # APPROX 05-HZ DELAY LOOP #
  2253. END
  2254. SPINTIME=SPINTIME+TIMEOFDAY-SPINSTART;
  2255. IOEND # OF SPINWHEELS #
  2256. PAGE # RELIABILITY/METERING HOOKS #
  2257.  
  2258.  
  2259. PROC FATALTRAP;
  2260. IOBEGIN(FATALTRAP)
  2261. #
  2262. ** FATALTRAP - INTERFACE FOR FAILING TASKS.
  2263. *
  2264. * FATALTRAP IS CALLED BY EDITING CODE WHICH DETECTS ITS OWN
  2265. * UNCORRECTABLE ALGORITHMIC INCONSISTENCY. THIS INTERFACE
  2266. * WAITS FOR ANY CIO CALL TO FINISH THEN BRANCHES DIRECTLY
  2267. * TO THE RUNJOBS EXECUTIVE.
  2268. *
  2269. * ENTRY FET - MAYBE ACTIVE.
  2270. *
  2271. * EXIT FET - COMPLETE.
  2272. * VIA AFTEREDIT LABEL.
  2273. *
  2274. * CALLS SMFRCL, AFTEREDIT.
  2275. #
  2276. XREF LABEL AFTEREDIT;
  2277. SMFRCL(FET); # WAIT IO DONE #
  2278. GOTO AFTEREDIT; # TERMINATE TASK #
  2279. END # OF FATALTRAP #
  2280.  
  2281.  
  2282. PROC ABTPAUSE;
  2283. IOBEGIN(ABTPAUSE)
  2284. #
  2285. ** ABTPAUSE - TRY TO CHECKPOINT WORKFILE AFTER ABORT.
  2286. *
  2287. * ABTPAUSE IS CALLED AS EDITING CODE BY THE RUNJOBS EXECUTIVE
  2288. * WHEN A TASK HAS ABORTED ITSELF. THE INTENT IS TO ATTEMPT
  2289. * TO CHECKPOINT THE WORKFILE BEFORE TRANSITIONING BACK TO
  2290. * SINGLE-USER. IF THIS CAN BE DONE, THEN THE SINGLE EDITOR
  2291. * WILL DETECT THE ABORTED FLAG IN THE DATA SEGMENT OF THE
  2292. * WORKFILE AND WILL KNOW THAT IT CANNOT PROCEED. ABTPAUSE
  2293. * MAY NOT SUCCEED, AND RUNJOBS IS RESPONSIBLE TO KEEP TRACK
  2294. * OF ABTPAUSE FAILURE AND INSTEAD CALL ABTKILL.
  2295. *
  2296. * CALLS PAUSEIO.
  2297. #
  2298. PAUSEIO;
  2299. IOEND # OF ABTPAUSE #
  2300.  
  2301.  
  2302. PROC ABTKILL;
  2303. IOBEGIN(ABTKILL)
  2304. #
  2305. ** ABTKILL - KILL OFF TASK AFTER DOUBLE ABORT.
  2306. *
  2307. * THE RUNJOBS EXECUTIVE CALLS ABTKILL AS A LAST RESORT WHEN A
  2308. * TASK HAS DELIBERATELY ABORTED ITSELF, THEN HAS ABORTED
  2309. * ITSELF A SECOND TIME WHEN ABTPAUSE ATTEMPTED TO CHECKPOINT
  2310. * THE WORKFILE. ABTKILL ATTEMPTS TO ZAP THE WORKFILE TO
  2311. * CONTAIN EXACTLY ONE WORD OF ZEROES, WHICH WOULD NOT BE
  2312. * ACCEPTED AS A VALID TRANSITION ONCE THE SINGLE-USER EDITOR
  2313. * GETS BACK IN CONTROL. THE INTENT IS TO BE AS CERTAIN AS
  2314. * POSSIBLE THAT THE SINGLE EDITOR WILL NOT PICK UP AND
  2315. * CONTINUE A HOPELESS EDIT SESSION.
  2316. *
  2317. * CALLS SMFRCL, WRITEO, REWRITR, SMFRCL.
  2318. *
  2319. * USES FET.
  2320. #
  2321. SMFRCL(FET);
  2322. FETRR=1;
  2323. WRITEO(FET,0);
  2324. REWRITR(FET,0);
  2325. SMFRCL(FET);
  2326. IOEND # OF ABTKILL #
  2327.  
  2328.  
  2329. CONTROL IFEQ METERING,1;
  2330.  
  2331. PROC BGNMETER;
  2332. BEGIN
  2333. #
  2334. ** BGNMETER - INSTRUMENT BEGINNING OF EDIT SESSION.
  2335. *
  2336. * BGNMETER ALLOWS THE SINGLE-USER EDITOR TO PASS DATA FROM
  2337. * ITS FILE-BUILD PROCESS, INTO THE CORRESPONDING TASK IN
  2338. * THE MULTI-USER EDITOR, WHICH CAN USE THIS INTERFACE TO
  2339. * GLOBALLY RECORD THE DATA.
  2340. *
  2341. * CALLS INSTRMNT1.
  2342. #
  2343. INSTRMNT1(INSTST"BGNEDT");
  2344. END
  2345.  
  2346.  
  2347. PROC WIOSTAT(ORDINAL);
  2348. BEGIN
  2349. #
  2350. ** WIOSTAT - WORKIO STATISTICS INTERFACE.
  2351. *
  2352. * WIOSTAT IS CALLED BY THE WORKFILE MANAGER AT NOTEWORTHY
  2353. * EVENTS SO THAT STATISTICS CAN BE INCREMENTED.
  2354. *
  2355. * ENTRY ORDINAL - WHICH ACCUMULATOR TO INCREMENT.
  2356. *
  2357. * CALLS INSTRMNT2.
  2358. #
  2359. ITEM ORDINAL;
  2360. INSTRMNT2(INSTST"WORKIO",ORDINAL);
  2361. END
  2362.  
  2363. CONTROL FI;
  2364. PAGE # FNT MANAGEMENT #
  2365.  
  2366.  
  2367. PROC RTRNWRKFIL;
  2368. IOBEGIN(RTRNWRKFIL)
  2369. #
  2370. ** RTRNWRKFIL - RETURN THE WORKFILE FNT.
  2371. *
  2372. * BEFORE SMFEX CAN TRANSITION A USER BACK TO THE SINGLE
  2373. * USER EDITOR, IT MUST GET RID OF ITS LOCAL FNT FOR THE
  2374. * USERS WORKFILE. RTRNWRKFIL DOES THIS AND IS
  2375. * DESIGNED TO BE CALLED BY RUNJOBS IN USER STATE JUST AFTER
  2376. * THE TASK HAS TERMINATED AT THE AFTEREDIT LABEL.
  2377. *
  2378. * ENTRY FET - SETUP.
  2379. *
  2380. * EXIT CURUSDONE - TRUE.
  2381. *
  2382. * CALLS RETERN, SMFRCL.
  2383. #
  2384. RETERN(FET,0);
  2385. CURUSDONE=TRUE; # ASSURE NO RECOVERY #
  2386. SMFRCL(FET);
  2387.  
  2388. IOEND # OF RTRNWRKFIL #
  2389.  
  2390.  
  2391. PAGE # LOGIN/LOGOUT CONTROL #
  2392.  
  2393.  
  2394. PROC SENDLOGOUT;
  2395. IOBEGIN(SENDLOGOUT)
  2396. #
  2397. ** SENDLOGOUT - TRANSMIT LAST OUTPUT AND ROLLIN SINGLE.
  2398. *
  2399. * SENDLOGOUT PERFORMS THE LAST PROCESSING WHEN A TASK
  2400. * COMPLETES ALL MULTI-USER PROCESSING. SENDLOGOUT SHOULD
  2401. * BE CALLED ONLY BY RUNJOBS AFTER THE TASK HAS EXITED
  2402. * AT LABEL AFTEREDIT AND AFTER THE WORKFILE LOCAL FNT HAS
  2403. * BEEN RETURNED. SENDLOGOUT ASSURES THAT ANY OUTPUT LEFT
  2404. * IN OUR BUFFERS IS SEND ON TO IAF, THEN TELLS IAF THE
  2405. * USER IS LEAVING MULTI-USER MODE, THEN ISSUES AN EESET
  2406. * FUNCTION TO CAUSE ROLLIN OF THE SINGLE USER JOB.
  2407. *
  2408. * THE TLX FUNCTION USED BY THE SINGLE USER JOB TO ROLLOUT
  2409. * WILL BE RECALLED TO VERIFY THAT SMFEX HAS PROPERLY
  2410. * DISPENSED WITH THE WORKFILE. TLX THEN CONFORMS TO IAF
  2411. * THAT THE MULTI-USER SESISON IS OVER.
  2412. *
  2413. * ENTRY TASKNXTTTO[CURTASK] - INDICATES RESIDUAL OUTPUT.
  2414. *
  2415. * EXIT TASKNXTTTO[CURTASK] - ZERO.
  2416. *
  2417. * CALLS TTOTRAP, TRANSMIT, EESET.
  2418. *
  2419. * USES TTOADDR, TTOLEN, TTOTYPE.
  2420. #
  2421. IF TASKNXTTTO[CURTASK] NQ 0 THEN
  2422. BEGIN
  2423. TTOADDR=0;
  2424. TTOLEN=0;
  2425. TTOTYPE=TTOST"FORCE";
  2426. TTOTRAP;
  2427. END
  2428. TASKTYPTTO[CURTASK]=SMF2IAF"LOGOUT";
  2429. TRANSMIT;
  2430. EESET((TTEQ*4096)+USEREJT[CURUSER]);
  2431.  
  2432. IOEND # OF SENDLOGOUT #
  2433. PAGE # TRANSMIT TO IAFEX #
  2434.  
  2435.  
  2436. PROC TRANSMIT;
  2437. IOBEGIN(TRANSMIT)
  2438. #
  2439. ** TRANSMIT - TRANSMIT A FUNCTION CODE/MESSAGE TO IAFEX.
  2440. *
  2441. * TRANSMIT IS USED FOR THE ISSUANCE OF ALL CODES TO IAFEX
  2442. * EXCEPT FOR THE SPECIAL CASE WHERE DOINPUT NEEDS TO
  2443. * DISCONNECT A TERMINAL IN SERIALIZED OPERATION FOR
  2444. * OVERFLOWED TABLES. TRANSMIT EXECUTES IN USER MODE, THUS
  2445. * THE EXECUTIVE HAS NO WAY TO SEND MESSAGES TO IAFEX EXCEPT
  2446. * FOR THE CASE ALREADY MENTIONED.
  2447. *
  2448. * EACH TASK HAS ITS OWN OUTPUT BUFFER WHICH IS USED TO
  2449. * ACCUMULATE AND BATCH OUTPUT TEXT TOGETHER TO MINIMIZE CALLS
  2450. * TO TRANSMIT. ONCE TRANSMIT IS CALLED, IT USES THE SCP/UCP
  2451. * FACILITY TO SEND THE TASK'S BUFFER TO IAF. IF THE SCP/UCP
  2452. * FUNCTIONS INDICATE THAT THE MESSAGE COULD NOT BE SENT TO
  2453. * IAF ON THIS RECALL CYCLE, THEN THE TASK IS DELAYED
  2454. * (ALLOWING OTHER TASKS TO EXECUTE IN PARALLEL) AND THE
  2455. * SCP/UCP OPERATION WILL BE TRIED AGAIN.
  2456. *
  2457. * ENTRY TASKTYPTTO[CURTASK] - FUNCTION CODE FOR IAFEX.
  2458. * TASKNXTTO[CURTASK] - AMOUNT OF TEXT TO GO WITH
  2459. * FUNCTION CODE.
  2460. * CURUSIAFNUM - IAFEX TERMINAL NUMBER.
  2461. * TTOWORDS, TTOBLOCKS - STATISTICAL ACCUMULATORS.
  2462. * CURUSLASTIM, TIMEOFDAY - ALSO FOR STATISTICS.
  2463. * CURUSRCVRY, CURUSINTRPT - INDICATE PURGE BUFFER.
  2464. *
  2465. * EXIT TTOWORDS, TTOBLOCKS - INCREMENTED.
  2466. * CURUSLASTIM, TIMEOFDAY - UP TO DATE.
  2467. *
  2468. * CALLS MELT, SYSTEM, INSTRMNT2, SMFDLY.
  2469. *
  2470. * USES IAFHEADER, P<SSCBUFFER>.
  2471. #
  2472. ITEM TMP1;
  2473.  
  2474. TRCSTR("NTR TRSMT$");
  2475. CONTROL IFEQ TRACEFLAG,1;
  2476. TMP1=TASKNXTTTO[CURTASK];
  2477. TRACEBOTH("NXTTTO$",TMP1);
  2478. TMP1=TASKTYPTTO[CURTASK];
  2479. TRACEBOTH("TYPTTO$",TMP1);
  2480. CONTROL FI;
  2481.  
  2482. CONTROL IFGQ PARANOIA,2;
  2483. IF TASKNXTTTO[CURTASK] GR SIZTTOBUF THEN MELT("TRANSMIT 1$");
  2484. IF CURUSIAFNUM GR MAXCONNECT THEN MELT("TRANSMIT 2$");
  2485. CONTROL FI;
  2486.  
  2487. IF CURUSINTRPT OR CURUSRCVRY THEN
  2488. BEGIN
  2489. TASKNXTTTO[CURTASK]=0;
  2490. IF SHUTDOWN EQ 2 OR TASKTYPTTO[CURTASK] EQ SMF2IAF"MSGOUT" OR
  2491. TASKTYPTTO[CURTASK] EQ SMF2IAF"PROMPT" THEN
  2492. BEGIN
  2493. TASKTYPTTO[CURTASK]=0;
  2494. IORET
  2495. END
  2496. END
  2497.  
  2498. IAFFUNC=TASKTYPTTO[CURTASK];
  2499. IAFLEN=TASKNXTTTO[CURTASK]+1;
  2500. IAFPTR=0;
  2501. IAFTERM=CURUSIAFNUM;
  2502. TTOBUFF[1]=IAFHEADER;
  2503. CONTROL IFEQ METERING,1;
  2504. TTOWORDS=TTOWORDS+IAFLEN;
  2505. TTOBLOCKS=TTOBLOCKS+1;
  2506. CONTROL FI;
  2507.  
  2508. TRYTOSEND: # BACK HERE IF RETRY NEEDED #
  2509.  
  2510. TTOBUFF[0]=0;
  2511. P&lt;SSCBUFFER>=LOC(TTOBUFFER);
  2512. SSCTYPE=O"3";
  2513. SSCCOUNT=IAFLEN;
  2514. SYSREQ("SSC",0,LOC(SSCBUFFER),IAFSSID);
  2515. IF SSCSTATUS LAN O"7776" EQ 0 THEN # NO ERROR #
  2516. BEGIN
  2517. CONTROL IFEQ TRACEFLAG,1;
  2518. ITEM TMP2,TMP3;
  2519. IAFHEADER=TTOBUFF[1]; # SINCE MAY HAVE LOST CTL #
  2520. TMP1=IAFFUNC;
  2521. TMP2=IAFTERM;
  2522. TMP3=IAFLEN-1;
  2523. P&lt;MOVFROM>=LOC(TTOBUFF[2]);
  2524. TRACEBOTH("FUNCOUT$",TMP1);
  2525. TRACEDEC(TMP2);
  2526. IF IAFLEN GR 1 THEN TRACEWORDS(MOVFROM,TMP3);
  2527. CONTROL FI;
  2528. CONTROL IFEQ METERING,1;
  2529. IF NOT CURUSOLDSND THEN
  2530. BEGIN
  2531. TMP1=TIMEOFDAY-CURUSLASTIM;
  2532. INSTRMNT2(INSTST"RSPNS",TMP1);
  2533. END
  2534. CONTROL FI;
  2535. IF TASKTYPTTO[CURTASK] EQ SMF2IAF"MSGOUT" THEN CURUSOLDSND=TRUE;
  2536. ELSE CURUSOLDSND=FALSE;
  2537. CURUSLASTIM=TIMEOFDAY;
  2538. IORET
  2539. END
  2540. ELSE IF SSCSTATUS LAN O"7776" EQ 4 THEN # IAF BUSY NOW #
  2541. BEGIN
  2542. SMFDLY;
  2543. GOTO TRYTOSEND;
  2544. END
  2545. ELSE MELT("CANT TALK TO IAFEX$");
  2546.  
  2547. IOEND # OF TRANSMIT #
  2548. PAGE # VOLUNTEER TO SURRENDER TASK #
  2549.  
  2550.  
  2551. PROC VOLUNTEER;
  2552. IOBEGIN(VOLUNTEER)
  2553. #
  2554. ** VOLUNTEER - SEE IF THIS TASK SHOULD SLOW DOWN.
  2555. *
  2556. * VOLUNTEER IS USED TO PREVENT A TASK FROM EXCESSIVE RESOURCE
  2557. * USAGE. EDITING CODE SHOULD CALL VOLUNTEER PERIODICALLY
  2558. * INSIDE ANY PROCESS WHICH IS POTENTIALLY LONG-RUNNING. NOTE
  2559. * THAT ANY CODE IN THE WORKFILE MANAGER (THE WORKIO MODULE)
  2560. * IS A "MUST COMPLETE" FUNCTION - THAT MEANS THAT VOLUNTEER
  2561. * CAN BE CALLED BY ACTUAL EDITING CODE BUT CANNOT BE CALLED
  2562. * FROM WORKIO ITSELF.
  2563. *
  2564. * VOLUNTEER FIRST CONSIDERS WHETHER THE TASK IS USING
  2565. * EXCESSIVE CPU TIME ON AN INSTANTANEOUS BASIS. THE
  2566. * OPERATING SYSTEM REAL TIME MILLISECOND CLOCK IS FRESHLY
  2567. * ACCESSED, AND THE CURRENT TIME IS COMPARED TO THE TIME
  2568. * TAKEN AT THE START OF THE RECALL CYCLE TO SEE IF MORE THAN
  2569. * A FEW MILLISECONDS OF CPU HAVE BEEN USED. A CALCULATION
  2570. * ATTEMPTS TO SELECT A THRESHOLD SUCH THAT SMFEX WILL NEVER
  2571. * USE MORE THAN ABOUT HALF OF THE CPU. THIS MEANS THAT FOR
  2572. * AN INSTALLATION WHICH INTENDS THAT SUBSTANTIALLY ALL OF THE
  2573. * CPU SHOULD BE USED FOR TEXT EDITING, SMFEX MAY BE
  2574. * UNSUITABLE AND THE SINGLE-USER EDITORS MAY BE BETTER.
  2575. *
  2576. * IF THE TASK IS CURRENTLY USING MORE THAN A FEW MILLISECONDS
  2577. * OF CPU, IT DELAYS, AND THE REMAINDER OF THE VOLUNTEER
  2578. * ALGORITHM WILL CONTINUE ON A LATER RECALL CYCLE.
  2579. *
  2580. * THE REMAINDER OF THE VOLUNTEER ALGORITHM CONSIDERS WHETHER
  2581. * A TASK HAS RESIDED IN ITS SWAPPED-IN MEMORY IMAGE FOR TOO
  2582. * MUCH REAL TIME. WE CALCULATE THE REAL TIME FROM THE TIME
  2583. * AT WHICH THE TASK SWAPPED IN UNTIL THE PRESENT TIME. IF
  2584. * THE TIME DELTA EXCEEDS THE "VOLTIME" THRESHOLD AND THERE IS
  2585. * QUEUED TERMINAL OUTPUT, THE TASK WILL SWAP OUT SO THE
  2586. * OUTPUT CAN BE SENT. IF THE TIME DELTA EXCEEDS THE
  2587. * THRESHOLD AND THERE ARE MORE USERS AWAITING SWAPIN THAN THE
  2588. * NUMBER OF TASKS FREE TO SWAP THEM IN, THEN THIS TASK WILL
  2589. * SWAPOUT SO ANOTHER USER CAN SWAPIN. IF THE NUMBER OF
  2590. * TERMINAL INPUT BUFFERS IS DOWN TO APPROXIMATELY ONE FOURTH
  2591. * OF THE TOTAL, THEN THIS TASK WILL SWAP OUT REGARDLESS OF
  2592. * WHETHER WE HAVE EXCEEDED THE THRESHOLD.
  2593. *
  2594. * THUS, THE "VOLTIME" THRESHOLD REPRESENTS THE AMOUNT OF TIME
  2595. * A TASK IS ASSURED THAT IT CAN REMAIN SWAPPED IN. IF THE
  2596. * TASK IS NOT PRODUCING OUTPUT AND THERE IS NO EXCESS QUEUE
  2597. * FOR SWAPIN, THE TASK CAN EXCEED THE TRESHOLD. BUT IF THERE
  2598. * IS A CRITICAL RESOURCE SHORTAGE (INPUT BUFFERS) THEN ALL
  2599. * BETS ARE OFF AND WE SWAP THIS TASK AS SOON AS IT HAS
  2600. * VOLUNTEERED, WITHOUT ALLOWING THE NORMAL GUARANTEED TIME.
  2601. *
  2602. * ENTRY TIMEOFDAY - TIME AT WHICH THIS RECALL CYCLE STARTED.
  2603. * OLDTIMEDAY - TIME FOR START OF PREVIOUS RECALL CYCLE,
  2604. * OR TIME OF VOLUNTEER EXECUTION WITHIN PREVIOUS
  2605. * RECALL CYCLE IF VOLUNTEER WAS CALLED.
  2606. * TASKTIME[CURTASK] - WHEN THIS TASK SWAPPED IN.
  2607. * TASKNXTTTO[CURTASK] - WHETHER OUTPUT IS PENDING.
  2608. * TASKSAVAIL - TOTAL USABLE TASKS.
  2609. * TASKSBUSY - NUMBER OF TASKS USED NOW.
  2610. * SWPQSIZE - NUMBER OF USERS AWAITING SWAPIN.
  2611. * REMAINTTI - NUMBER OF UNUSED INPUT BUFFERS.
  2612. *
  2613. * EXIT TIMEOFDAY - UP TO DATE.
  2614. * TASKNXTTTO[CURTASK] - CLEARED IF SWAPPED.
  2615. * TASKTIME[CURTASK] - NEW VALUE IF SWAPPED.
  2616. * CURUSCRUNCH - TRUE IF SWAP FOR OVERTIME BUT NO OUTPUT.
  2617. * TASKREQUE[CURTASK] - TRUE IF SWAP NOT FOR OUTPUT.
  2618. *
  2619. * CALLS RTIME, MIN, MAX, SMFDLY, INSTRMNT1, INSTRMNT2,
  2620. * TTSYNC, TTOTRAP.
  2621. *
  2622. * USES TTOADDR, TTOLEN, TTOTYPE.
  2623. #
  2624. ITEM DELTA, SURRENDER;
  2625.  
  2626. RTIME(NEWTIMEDAY);
  2627. NEWTIMEDAY=B&lt;24,36>NEWTIMEDAY;
  2628. DELTA=MAX(50,MIN(10,(TIMEOFDAY-OLDTIMEDAY)/2));
  2629. IF NEWTIMEDAY-TIMEOFDAY GR DELTA THEN
  2630. BEGIN
  2631. SMFDLY;
  2632. CONTROL IFEQ METERING,1;
  2633. INSTRMNT1(INSTST"DROPCPU");
  2634. CONTROL FI;
  2635. END
  2636.  
  2637. # NEXT CODE IS NON-REENTRANT, MUST RUN INSTANTANEOUSLY #
  2638.  
  2639. DELTA=TIMEOFDAY-TASKTIME[CURTASK];
  2640. SURRENDER=0;
  2641.  
  2642. # TRY TO MOVE IF SITTING ON TYPABLE OUTPUT FOR A LONG TIME #
  2643. IF TASKNXTTTO[CURTASK] NQ 0 AND DELTA GQ VOLTIME*4
  2644. THEN SURRENDER=1;
  2645.  
  2646. # ALSO TRY TO MOVE IF SHORT ON TASKS FOR A SHORT TIME #
  2647. IF TASKSAVAIL-TASKSBUSY LS SWPQSIZE AND DELTA GQ VOLTIME
  2648. THEN SURRENDER=2;
  2649.  
  2650. # MOVE IF CRITICAL RESOURCE SHORTAGE REGARDLESS OF TIME #
  2651. IF REMAINTTI LQ (NUMTTIBUF+3)/4
  2652. THEN SURRENDER=3;
  2653.  
  2654. # END OF INSTANTANEOUS ALGORITHM #
  2655.  
  2656. IF SURRENDER NQ 0 THEN # FACE WRITING ON WALL #
  2657. BEGIN
  2658. TRCBOTH("PREEMPT$",CURUSER);
  2659. CONTROL IFEQ METERING,1;
  2660. INSTRMNT2(INSTST"PREEMPT",SURRENDER);
  2661. CONTROL FI;
  2662. IF SCREENMODE THEN
  2663. BEGIN # IF IN SCREEN MODE #
  2664. VDSYNCH; # MUST PRECEED TASKNXTTTO CHECK #
  2665. END # SINCE OUTPUT MAY BE FLUSHED #
  2666. ELSE
  2667. BEGIN # LINE MODE #
  2668. TTSYNC; # MUST PRECEED TASKNXTTTO CHECK #
  2669. END # SINCE OUTPUT MAY BE FLUSHED #
  2670. IF TASKNXTTTO[CURTASK] EQ 0 THEN
  2671. BEGIN # IF NO OUTPUT QUEUED FOR USER #
  2672. CURUSCRUNCH=TRUE; # NO OUTPUT, JUST CRUNCHING #
  2673. TASKREQUE[CURTASK]=TRUE; # SHOULD BE REQUEUED #
  2674. END
  2675. TTOADDR=0;
  2676. TTOLEN=0;
  2677. TTOTYPE=TTOST"FORCE";
  2678. TTOTRAP;
  2679. END
  2680.  
  2681. IOEND # OF VOLUNTEER #
  2682. PAGE # TTY INPUT HOOK #
  2683.  
  2684.  
  2685. PROC TTITRAP;
  2686. IOBEGIN(TTITRAP)
  2687. #
  2688. ** TTITRAP - PROVIDE EDITOR CODE WITH INPUT TEXT.
  2689. *
  2690. * TTITRAP IS CALLED BY THE EDITOR IN LIEU OF CIO READ
  2691. * FUNCTIONS AGAINST AN INPUT FET. CALLING TTITRAP INSTEAD OF
  2692. * CIO IS DONE BY CONDITIONAL COMPILATION OF CODE IN THE
  2693. * TERMIO MODULE. THE EDITOR IS NOT ALLOWED TO OBTAIN INPUT
  2694. * BY ANY MEANS EXCEPT TO CALL TERMIO AND LET IT DECIDE WHICH
  2695. * MECHANISM IS APPROPRIATE FOR THE VERSION OF THE EDITOR.
  2696. *
  2697. * IN ADDITION TO PROVIDING INPUT, TTITRAP ALSO PROVIDES A
  2698. * MEANS TO PURGE ANY UNUSED INPUT FROM THE BUFFERS CHAINS.
  2699. * THIS IS INDICATED BY A NEGATIVE VALUE IN THE TTILEN
  2700. * PARAMETER.
  2701. *
  2702. * WHEN INPUT IS DESIRED, TERMIO USES A POSITIVE VALUE IN THE
  2703. * TTILEN PARAMETER TO INDICATE THE MAXIMUM NUMBER OF WORDS IT
  2704. * CAN ACCEPT. THE WORKING BUFFER IS POINTED TO BY THE
  2705. * TTIADDR PARAMETER. THE TTINEXT PARAMETER IS MAINTAINED BY
  2706. * THIS ROUTINE TO KEEP TRACK OF WHAT PORTIONS OF THE CURRENT
  2707. * BUFFER CHAIN HAVE ALREADY BEEN TRANSMITTED.
  2708. *
  2709. * INPUT FROM IAFEX IS MAINTAINED BY SMFEX, UNTIL TTITRAP IS
  2710. * READY TO PASS ON TO THE EDITING CODE, IN A CHAIN OF ONE OR
  2711. * MORE TERMINAL INPUT BUFFERS. ONE BUFFER IS CHAINED FOR
  2712. * EACH MESSAGE FRAGMENT SENT BY IAFEX. TTITRAP MAINTAINS THE
  2713. * TTILAST PARAMETER, WHICH IS THE TEXT OF THE LAST WORD
  2714. * PASSED TO TERMIO, TO KNOW WHETHER THE PREVIOUS TTITRAP
  2715. * CYCLE ENCOUNTERED A ZERO BYTE TERMINATOR. THIS ENABLES
  2716. * TTITRAP TO KNOW WHETHER THE EDITING TASK IS IN THE MIDDLE
  2717. * OF A SERIES OF FRAGMENTS OR IS AWAITING THE FIRST FRAGMENT
  2718. * OF A MESSAGE.
  2719. *
  2720. * IF TTITRAP DETERMINES THAT THE TASK IS IN THE MIDDLE OF A
  2721. * SERIES OF FRAGMENTS, BUT DOES NOT YET HAVE THE NEXT
  2722. * FRAGMENT FROM IAFEX, TTITRAP WILL ATTEMPT TO KEEP THE TASK
  2723. * DELAYING IN MEMORY, USING THE SPINWHEELS FUNCTION. THIS IS
  2724. * DONE BECAUSE THERE IS AN EXCELLENT PROBABILITY THAT THE
  2725. * NEXT INPUT FRAGMENT WILL ARRIVE FROM IAFEX WITHIN A FEW
  2726. * MILLISECONDS. ON THE OTHER HAND, WHEN THE EDITING TASK
  2727. * ASKS FOR THE FIRST FRAGMENT OF A MESSAGE AND NO TEXT HAS
  2728. * ARRIVED YET FROM IAFEX, IT IS LIKELY THAT SEVERAL SECONDS
  2729. * WILL PASS BEFORE THE INPUT ARRIVES, SO THAT TASK IS ALLOWED
  2730. * TO SWAPOUT.
  2731. *
  2732. * ONCE THE TASK ADVANCES THRU TTITRAP BEYOND ANY WHEELSPIN OR
  2733. * ANY SWAPOUT, TTITRAP ASSEMBLES AS MUCH INPUT TEXT AS IT
  2734. * CAN, UNTIL EITHER THE TTILEN PARAMETER IS EXHAUSTED OR THE
  2735. * END OF ONE BUFFER IS REACHED. TEXT FROM THE NEXT BUFFER OF
  2736. * A CHAIN OF SEVERAL FRAGMENTS CANNOT BE PROCESSED UNTIL THE
  2737. * NEXT CALL TO TTITRAP. THIS MEANS THAT THE SIZE OF EACH
  2738. * FRAGMENT ALLOWED BY IAFEX AND SMFEX MUST BE ADEQUATE FOR
  2739. * COMPLETE INPUTS WHEN THE EDITOR IS USED IN LINE MODE. THIS
  2740. * RESTRICTION IS IN EFFECT BECAUSE THE LINE EDITOR REQUESTS
  2741. * INPUT IN COMPLETE LINE IMAGES. THE SCREEN EDITOR, HOWEVER,
  2742. * ASKS FOR INPUT ONE WORD AT A TIME, SO MULTIPLE FRAGMENTS
  2743. * CAN BE PROCESSED WITH MULTIPLE TTITRAP CALLS.
  2744. *
  2745. * WHEN TTITRAP DECIDES TO SWAP THE TASK OUT, IT CALLS PAUSEIO
  2746. * IN THE WORKFILE MANAGER. THIS IS DONE BECAUSE WORKIO HOLDS
  2747. * SOME TRANSIENT RESOURCES, SUCH AS ITS CIRCULAR BUFFER, AND
  2748. * NEEDS THE OPPORTUNITY TO COMPLETE ITS USAGE OF THESE
  2749. * RESOURCES.
  2750. *
  2751. *
  2752. * ENTRY TTILEN - NEGATIVE MEANS PURGE UNUSED INPUT.
  2753. * POSITIVE IS TASKS CAPACITY FOR TEXT.
  2754. * TTIADDR - WHERE THE TEXT SHOULD GO.
  2755. * CURUSTTIBUF - FIRST BUFFER LINKAGE.
  2756. * TTINEXT - WHERE TTITRAP PREVIOUS EXTRACTED TEXT.
  2757. * TTILAST - LAST WORD OF TEXT FROM PREVIOUS TTITRAP.
  2758. * RUNTIME - FOR STATISTICS.
  2759. * TIMEOFDAY, TASKTIME[CURTASK] - FOR STATISTICS.
  2760. * ACCTCIO, ACCTTRANS - STATISTICS/ACCOUNTING.
  2761. * TTOWORDS, TTOBLOCKS - FOR STATISTICS.
  2762. * TTIBUFADDR[ALL] - SETUP.
  2763. * TTIBUFLNK[ALL] - LINKAGES.
  2764. * TTIBUFLEN[ALL] - FRAGMENT SIZES.
  2765. * TTIBITS - ALLOCATION BITMASK FOR BUFFERS.
  2766. *
  2767. * EXIT TTINEXT - INCREMENTED.
  2768. * CURUSTTIBUF - ADVANCED/CLEARED VIA LINKAGE.
  2769. * TIMEOFDAY - UP TO DATE.
  2770. * TASKTIME[CURTASK] - TIME OF SWAPOUT IF ANY.
  2771. * RUNTIME, ACCTCIO, ACCTTRANS - INCREMENTED.
  2772. * SPINTIME, RUNTIME, CIOCOUNT - CLEARED IF SWAPPED.
  2773. * CURUSOKOUT - TRUE.
  2774. * TTILEN - DECREMENTED.
  2775. * TTILAST - UPDATED.
  2776. * REMAINTTI - INCREMENTED IF BUFFER EMPTIED.
  2777. * TTOWORDS, TTOBLOCKS - CLEARED IF SWAPPED.
  2778. *
  2779. * CALLS PURGETTI, SPINWHEELS, CLEARQUE, PAUSEIO, INSTRMNT1,
  2780. * INSTRMNT2, INSTRMNT3, TTOTRAP, MIN, MOVEWD, DEALLOC.
  2781. *
  2782. * USES TTOLEN, TTOTYPE.
  2783. #
  2784. ITEM TMP1, TMP2, TMP3;
  2785. ITEM QUESTION1 I=O"7100 0013 0000 0000 0000"; # PROMPT ONE #
  2786. ITEM QUESTION2 I=O"7155 0013 0000 0000 0000"; # PROMPT TWO #
  2787. ITEM XPTINCTL I=O"0006 4704 0015 0000 0000"; # XPARENT INPUT #
  2788.  
  2789. TRCSTR("NTR ITRP$");
  2790.  
  2791. IF TTILEN LS 0 THEN # PURGE ANY BUFFERS #
  2792. BEGIN
  2793. IF CURUSTTIBUF NQ 0 THEN PURGETTI;
  2794. TTINEXT=0;
  2795. IORET
  2796. END
  2797.  
  2798. IF CURUSTTIBUF EQ 0 AND B&lt;48,12>TTILAST NQ 0 THEN
  2799. BEGIN # DELAY SINCE MORE INPUT DUE ASAP #
  2800. SPINWHEELS; # DELAY TILL INPUT ARRIVES OR TIMEOUT #
  2801. CLEARQUE;
  2802. END
  2803.  
  2804. IF NOT CURUSOKOUT THEN # FIRST TRANSACTION #
  2805. BEGIN
  2806. CURUSOKOUT=TRUE;
  2807. IF SCREENMODE THEN
  2808. BEGIN
  2809. ROWPAINT[COMMANDROW]=TRUE;
  2810. END
  2811. ELSE
  2812. BEGIN
  2813. TTOADDR=LOC(QUESTION1);
  2814. TTOLEN=1;
  2815. TTOTYPE=TTOST"NORMAL";
  2816. TTOTRAP;
  2817. END
  2818. END
  2819.  
  2820. IF CURUSTTIBUF EQ 0 THEN # NORMAL TRANSACTION SO SWAPOUT #
  2821. BEGIN
  2822. PAUSEIO; # LET WORKIO PP'S DROP #
  2823. RUNTIME=TIMEOFDAY-TASKTIME[CURTASK]+RUNTIME;
  2824. TASKTIME[CURTASK]=TIMEOFDAY;
  2825. ACCTCIO=ACCTCIO+CIOCOUNT;
  2826. ACCTTRANS=ACCTTRANS+1;
  2827. CONTROL IFEQ METERING,1;
  2828. INSTRMNT2(INSTST"TASKUTIL",RUNTIME);
  2829. INSTRMNT3(INSTST"EDTCIO",RUNTIME-SPINTIME,CIOCOUNT);
  2830. INSTRMNT1(INSTST"TRANS");
  2831. CONTROL FI;
  2832. IF NOT CURUSINTRPT THEN
  2833. BEGIN # NO FRESH BREAK, CAN PROMPT #
  2834. TTOADDR=LOC(QUESTION2);
  2835. TTOLEN=1;
  2836. IF SCREENMODE THEN # IF SCREEN MODE #
  2837. BEGIN
  2838. IF TABTYPHEAD[0] THEN TTOLEN=0; # IF TYPEAHEAD USED #
  2839. ELSE TTOADDR=LOC(XPTINCTL); # NO TYPEAHEAD #
  2840. END
  2841. TTOTYPE=TTOST"PROMPT";
  2842. TTOTRAP;
  2843. END
  2844. SPINTIME=0;
  2845. RUNTIME=0;
  2846. CIOCOUNT=0;
  2847. CONTROL IFEQ METERING,1;
  2848. INSTRMNT3(INSTST"XMIT",TTOWORDS,TTOBLOCKS);
  2849. TTOBLOCKS=0;
  2850. TTOWORDS=0;
  2851. CONTROL FI;
  2852. END
  2853. # NOW WE KNOW WE HAVE SOMETHING #
  2854.  
  2855. MEM[TTIADDR]=0; # ASSURE DEFAULT NULL LINE #
  2856. WHYLE CURUSTTIBUF NQ 0 AND TTILEN GR 0 DO
  2857. BEGIN
  2858. TMP1=CURUSTTIBUF;
  2859. P&lt;MOVFROM>=TTIBUFADDR[TMP1]+TTINEXT;
  2860. P&lt;MOVTO>=TTIADDR;
  2861. TMP2=TTIBUFLEN[TMP1]-TTINEXT;
  2862. TMP3=MIN(TMP2,TTILEN);
  2863. MOVEWD(TMP3,MOVFROM,MOVTO);
  2864. TTINEXT=TTINEXT+TMP3; # INCREMENT SOURCE ADDR #
  2865. TTILEN=TTILEN-TMP3; # DECREMENT CALLERS COUNT #
  2866. TTILAST=MEM[LOC(MOVFROM)+TMP3-1]; # SHOWS WHETHER EOL SEEN #
  2867. IF TTINEXT GQ TTIBUFLEN[TMP1] THEN
  2868. BEGIN # RELEASE THIS BUFFER, POINT NEXT #
  2869. TTINEXT=0;
  2870. DEALLOC(TTIBITS,TMP1,NUMTTIBIT);
  2871. REMAINTTI=REMAINTTI+1;
  2872. CURUSTTIBUF=TTIBUFLNK[TMP1];
  2873. END
  2874. END
  2875.  
  2876. IOEND # OF TTITRAP #
  2877. PAGE # TTY OUTPUT AND SWAPOUT HOOK #
  2878.  
  2879.  
  2880. PROC TTOTRAP;
  2881. IOBEGIN(TTOTRAP)
  2882. #
  2883. ** TTOTRAP - QUEUE/ISSUE OUTPUT, SWAP AS NEEDED.
  2884. *
  2885. * TTOTRAP IS CALLED BY EDITOR CODE IN LIEU OF CIO WRITE
  2886. * FUNCTIONS AGAINST AN OUTPUT FET. EDITING CODE IS REQUIRED
  2887. * TO INTERFACE ALL OUTPUT THRU THE TERMIO MODULE, WHICH USES
  2888. * CONDITIONAL COMPILATION TO SELECT THE RIGHT TECHNIQUE OF
  2889. * OUTPUT FOR THE VERSION OF THE EDITOR.
  2890. *
  2891. * TTOTRAP IS ALSO USED BY THE VOLUNTEER AND TTITRAP ROUTINES
  2892. * OF SMFEX. TTOTRAP PROVIDES SWAPOUT LOGIC FOR THOSE CALLERS
  2893. * TOGETHER WITH ISSUANCE OF RESIDUAL OUTPUT.
  2894. *
  2895. * TTOTRAP IS CONTROLLED PRIMARILY BY THE TTOTYPE PARAMETER.
  2896. * THE "NORMAL" VALUE INDICATES THAT THE CALLER'S INTENT IS TO
  2897. * OFFER SOME OUTPUT TEXT. TTOTRAP QUEUES THIS TEXT INTO THE
  2898. * TASK'S UNIQUE OUTPUT BUFFER AS POSSIBLE, CALLING THE
  2899. * TRANSMIT ROUTINE TO SEND TO IAFEX WHENEVER THE BUFFER IS
  2900. * FULL. FOR THIS TYPE OF COMMUNICATION TO IAFEX, TTOTRAP
  2901. * THEN USES THE SPINWHEELS FUNCTION TO HOLD ONTO THE TASK FOR
  2902. * A FEW EXTRA MILLISEONDS, SINCE THERE IS ABOUT AN EVEN
  2903. * CHANCE THAT IAFEX WILL QUICKLY RESPOND AND ASK SMFEX TO
  2904. * CONTINUE TASK EXECUTION. IF IAFEX FAILS TO RESPOND WITHIN
  2905. * THE LIMITATIONS OF THE SPINWHEELS ROUTINE, THEN TTOTRAP
  2906. * ASSUMES IT WILL BE SEVERAL SECONDS BEFORE IAFEX AND THE
  2907. * NETWORK CAN ACCEPT ANY OTHER OUTPUT FOR THIS USER, AND
  2908. * TTOTRAP SWAPS THE TASK OUT.
  2909. *
  2910. * THE SECOND BASIC VALUE FOR THE TTOTYPE PARAMETER IS
  2911. * "PROMPT". THIS IS USED WHEN TTITRAP CALLS TTOTRAP.
  2912. * TTOTRAP IS EXPECTED TO IMMEDIATELY TRANSMIT ANY RESIDUAL
  2913. * QUEUE OF OUTPUT TEXT TO IAFEX, THEN SWAP THE TASK OUT.
  2914. * TTOTRAP ASSUMES THAT THE CALLER (TTITRAP) HAS ALREADY MADE
  2915. * A DETERMINATION AS TO LOW PROBABILITY OF RAPID REPLY FROM
  2916. * IAFEX.
  2917. *
  2918. * THE THIRD AND LAST BASIC FUNCTION OF TTOTRAP IS THE "FORCE"
  2919. * VALUE OF THE TTOTYPE PARAMETER. THIS IS USED BY VOLUNTEER
  2920. * WHEN IT IS DETERMINED THAT SOME RESIDUAL TEXT HAS BEEN
  2921. * QUEUED IN THE TASK'S OUTPUT BUFFER FOR AN EXCESSIVE REAL
  2922. * TIME DELAY, AND OUGHT TO BE SENT TO THE USER'S TERMINAL.
  2923. * WHEN TTOTRAP PROCESSES THE "FORCE" FUNCTION, IT TRANSMITS
  2924. * THE BUFFER CONTENT TO IAF AND PROCEEDS TO SWAP THE TASK
  2925. * WITHOUT ANY USAGE OF THE SPINWHEELS FUNCTION.
  2926. *
  2927. * WHEN TTOTRAP DECIDES TO SWAPOUT, IT MUST CALL PAUSEIO IN
  2928. * THE WORKFILE MANAGER. THIS IS BECAUSE WORKIO DEALS WITH
  2929. * SOME TRANSIENT RESOURCE, SUCH AS ITS CIRCULAR BUFFER, AND
  2930. * NEEDS THE OPPORTUNITY TO COMPLETE ITS USAGE OF SUCH
  2931. * RESOURCES.
  2932. *
  2933. * ENTRY TTOTYPE - FUNCTION CODE.
  2934. * TTOADDR - ADDRESS OF TEXT.
  2935. * TTOLEN - LENGTH OF TEXT.
  2936. * TASKNXTTTO[CURTASK] - AMOUNT OF TEXT ALREADY QUEUED.
  2937. * TTOBUFFER - ADDRESS OF THIS TASK'S BUFFER.
  2938. * ALL SPINWHEELS PARAMETERS SETUP.
  2939. *
  2940. * EXIT TTOLEN - DECREMENTED.
  2941. * TTOADDR - INCREMENETED.
  2942. * TASKNXTTTO[CURTASK] - AMOUNT OF TEXT NOW IN BUFFER.
  2943. * RUNTIME - INCREMENTED IF SWAPOUT.
  2944. * ACCTOUT - INCREMENTED.
  2945. *
  2946. * CALLS MIN, MOVEWD, MELT, INSTRMNT1, TRANSMIT,
  2947. * SPINWHEELS, CLEARQUE, PAUSEIO, ENDTRANS.
  2948. *
  2949. * USES TTOQUIT, TASKTYPTTO[CURTASK].
  2950. #
  2951. ITEM TMP1 I; # TEMPORARY STORAGE #
  2952. ITEM TMP2 I; # TEMPORARY STORAGE #
  2953. ITEM ENDBLOCK I=O"0014 0000 0000 0000 0000"; # BLOCK TERMINATOR #
  2954.  
  2955. TRCSTR("NTR OTRP$");
  2956.  
  2957. IF NOT CURUSOKOUT THEN IORET # FIRST TRANS ONLY #
  2958.  
  2959. P&lt;MOVFROM>=TTOADDR;
  2960. ACCTOUT=ACCTOUT+TTOLEN; # ACCOUNT FOR OUTPUT #
  2961.  
  2962. TTOQUIT=FALSE;
  2963. WHYLE NOT TTOQUIT DO # SEND ALL TEXT #
  2964. BEGIN
  2965. TMP1=SIZTTOBUF-TASKNXTTTO[CURTASK]-1; # AVAILABLE ROOM #
  2966. TMP2=MIN(TMP1,TTOLEN); # AMOUNT TO SEND #
  2967. P&lt;MOVFROM>=TTOADDR;
  2968. P&lt;MOVTO>=LOC(TTOBUFFER)+2+TASKNXTTTO[CURTASK];
  2969. MOVEWD(TMP2,MOVFROM,MOVTO);
  2970. TTOLEN=TTOLEN-TMP2;
  2971. TTOADDR=TTOADDR+TMP2;
  2972. TASKNXTTTO[CURTASK]=TASKNXTTTO[CURTASK]+TMP2;
  2973. TASKTYPTTO[CURTASK]=0; # DETERMINE TRANSMIT #
  2974. CONTROL IFGQ PARANOIA,4;
  2975. IF TASKNXTTTO[CURTASK] GR SIZTTOBUF THEN MELT("TTOTRAP 1$");
  2976. CONTROL FI;
  2977. CONTROL IFEQ METERING,1;
  2978. IF TASKNXTTTO[CURTASK] GQ SIZTTOBUF-1
  2979. THEN INSTRMNT1(INSTST"XSTTO");
  2980. CONTROL FI;
  2981. IF (TTOTYPE EQ TTOST"FORCE" AND TASKNXTTTO[CURTASK] NQ 0)
  2982. OR TASKNXTTTO[CURTASK] GQ (SIZTTOBUF-1)
  2983. THEN TASKTYPTTO[CURTASK]=SMF2IAF"MSGOUT";
  2984. IF TTOTYPE EQ TTOST"PROMPT" AND TTOLEN EQ 0
  2985. THEN TASKTYPTTO[CURTASK]=SMF2IAF"PROMPT";
  2986. IF TASKTYPTTO[CURTASK] NQ 0 THEN # TRANSMIT #
  2987. BEGIN
  2988. P&lt;MOVFROM>=LOC(ENDBLOCK); # ADD 0014 CONTROL BYTE #
  2989. P&lt;MOVTO>=LOC(TTOBUFFER)+2+TASKNXTTTO[CURTASK];
  2990. MOVEWD(1,MOVFROM,MOVTO);
  2991. TASKNXTTTO[CURTASK]=TASKNXTTTO[CURTASK]+1;
  2992. TRANSMIT; # TRANSMIT BUFFER TO IAFEX #
  2993. TASKNXTTTO[CURTASK]=0;
  2994. IF TTOTYPE NQ TTOST"FORCE" AND TASKTYPTTO[CURTASK]
  2995. EQ SMF2IAF"MSGOUT" THEN # ATTEMPT CONTINUE #
  2996. BEGIN
  2997. SPINWHEELS; # LOOK FOR QUICK ACKNOWLEGE #
  2998. IF TASKREQUE[CURTASK] THEN # CAN CONTINUE #
  2999. BEGIN
  3000. TRCSTR("KWIK TOCIN$");
  3001. CLEARQUE; # ACKNOWLEDGE #
  3002. TASKTYPTTO[CURTASK]=0; # AVOID SWAPOUT #
  3003. CONTROL IFEQ METERING,1;
  3004. INSTRMNT1(INSTST"KWIKTOC");
  3005. CONTROL FI;
  3006. END
  3007. END
  3008. END
  3009. IF TASKTYPTTO[CURTASK] NQ 0 OR TTOTYPE NQ TTOST"NORMAL" THEN
  3010. BEGIN
  3011. PAUSEIO;
  3012. RUNTIME=RUNTIME+TIMEOFDAY-TASKTIME[CURTASK];
  3013. ENDTRANS;
  3014. END
  3015. IF TTOLEN LQ 0 THEN TTOQUIT=TRUE;
  3016. END
  3017.  
  3018. IOEND # OF TTOTRAP #
  3019. PAGE # SWAPPING ROUTINE #
  3020.  
  3021.  
  3022. PROC SWAP;
  3023. IOBEGIN(SWAP)
  3024. #
  3025. ** SWAP - SWAP THIS TASK IN OR OUT.
  3026. *
  3027. * THE SWAP ROUTINE READS OR WRITE THE SWAP PAGE FOR THE
  3028. * CURRENTLY EXECUTING TASK. FOR A SWAPIN, WE READ THE PAGE
  3029. * ALREADY ASSIGNED TO THE USER. FOR A SWAPOUT, WE ASSIGN A
  3030. * PAGE. THE FIRST PRIORITY IN PAGE SELECTION IS EXTENDED
  3031. * MEMORY IF AVAILABLE, HEALTHY, AND NOT YET FILLED UP. THE
  3032. * LOWER PRIORITY IS TO SELECT A DISK PAGE. DISK PAGES ARE
  3033. * PHASED OR INTERLEAVED ROUND-ROBIN ACROSS THE SEVERAL SWAP
  3034. * DATABASES.
  3035. *
  3036. * THE SWAP ROUTINE CAN RECOVER FROM A PARITY ERROR IN AN
  3037. * EXTENDED MEMORY TRANSFER, BUT DOES NOT ATTEMPT TO HANDLE
  3038. * DEVICE ERRORS ON DISKS. WHEN AN ERROR IS DETECTED FROM
  3039. * EXTENDED MEMORY, A USER BEING SWAPPED IN WILL HAVE HIS TASK
  3040. * ABORTED, WHILE A USER BEING SWAPPED IS UNHARMED. ERROR
  3041. * RECOVERY INCLUDES THE FAULT-OUT OF THE BAD PAGE,
  3042. * DETERMINATION WHETHER THE ENTIRE EXTENDED MEMORY FIELD
  3043. * LENGTH SHOULD BE ABANDONED DUE TO WIDESPREAD ERRORS, AND
  3044. * FOR SWAPOUT WE ALSO ALLOCATE ANOTHER PAGE AND TRY THE SWAP
  3045. * AGAIN.
  3046. *
  3047. * WHILE SWAP IS EXECUTING, THE DISPATCHING AREA IN THE COMMON
  3048. * BLOCK IS CONSIDERED TO BE IRRELEVANT. THEREFORE, THE
  3049. * ROUTINE WHICH MANAGES THE BRUTE-FORCE SHUFFLING OF THE
  3050. * COMMON BLOCK (SUBROUTINE GETCOMON) NEEDS TO KNOW WHEN
  3051. * SWAPPING IS IN EFFECT. THIS SWAP ROUTINE IS THUS REQUIRED
  3052. * TO TURN THE TASKSWPNOW FLAG ON AT ENTRY TIME AND TO TURN IT
  3053. * OFF AT EXIT TIME. NO REENTRANT EVENTS CAN OCCUR BETWEEN
  3054. * THE ACTUAL ENTRY OR EXIT AND THE SETTING OF THE TASKSWPNOW
  3055. * FLAG.
  3056. *
  3057. * ENTRY TASKSWPIN[CURTASK] - DIRECTION OF SWAP.
  3058. * TIMEOFDAY - CURRENT.
  3059. * SWAPBITS - ALLOCATION BITMASK.
  3060. * P<SWAPMASK> - ENABLES/DISABLES EXTENDED MEMORY PAGES.
  3061. * CURUSSWPPAG - USERS PAGE FOR SWAPIN.
  3062. * TASKADDR[CURTASK] - MEMORY ADDRESS FOR SWAP PAGE.
  3063. * SWAPLEN - LENGTH OF A PAGE IN WORDS.
  3064. * SWAPPRUS - LENGTH OF A PAGE IN SECTORS.
  3065. * ECSERRORS - PREVIOUS EXTENDED MEMORY ERRORS.
  3066. * SWPFETDONE[ALL] - INTERLOCKS ON DISK FILES.
  3067. * SWPFET[ALL] - THE DISK FET'S.
  3068. * MAXSWPPAG - HIGHEST DISK PAGE CREATED TO DATE.
  3069. *
  3070. * EXIT TIMEOFDAY - CURRENT.
  3071. * SWAPBITS - UPDATED.
  3072. * SWAPGOOD - EXTENDED MEMORY ERRORS FAULTED HERE.
  3073. * ECSERRORS - INCREMENTED IF ERRORS.
  3074. * MAXSWPPAG - INCREMENTED IF HIGHWATERMARK RAISED.
  3075. * TASKTIME[CURTASK] - TIMEOFDAY.
  3076. * STATUSMSG - MAY CONTAIN ERROR MSG.
  3077. * CURUSSWPPAG - PAGE SELECTED FOR SWAPOUT.
  3078. * CURUSVICTIM - TRUE IF ECS PARITY ERROR ON SWAPIN.
  3079. *
  3080. * CALLS ALLOC, MELT, INSTRMNT1, READECS, WRITECS,
  3081. * FORCEALLOC, SMFDLY, MAKEFET, READ, WRITER, REWRITR,
  3082. * SMFRCL, INSTRMNT2.
  3083. *
  3084. * USES TASKSWPNOW[CURTASK], TASKSWPFIL[CURTASK],
  3085. * TASKSWPPRU[CURTASK], P<MOVFROM>, P<MOVTO>, SWPFET.
  3086. #
  3087. ITEM TMP1,TMP2;
  3088.  
  3089. # SWAP IS REQUIRED TO SET TASKSWPNOW BEFORE ANY DELAYS OCCUR #
  3090.  
  3091. TRCSTR("NTR SWP$");
  3092. TASKSWPNOW[CURTASK]=TRUE;
  3093. TASKTIME[CURTASK]=TIMEOFDAY;
  3094.  
  3095. SWAPSTART:
  3096.  
  3097. IF NOT TASKSWPIN[CURTASK] THEN # ALLOC PAGE #
  3098. BEGIN
  3099. ALLOC(SWAPBITS,SWAPMASK,TMP1,NUMSWPBIT);
  3100. IF TMP1 EQ 0 THEN MELT("SWPO 2$");
  3101. CURUSSWPPAG=TMP1; # SAVE INVIOLATE #
  3102. END
  3103.  
  3104. TRCBOTH("PAGE$",CURUSSWPPAG);
  3105.  
  3106. IF CURUSSWPPAG LQ NUMSWPECS THEN # ECS SWAP #
  3107. BEGIN
  3108. TRCSTR("SWPECS$");
  3109. CONTROL IFEQ ECSCODE,0;
  3110. CONTROL IFGQ PARANOIA,1;
  3111. MELT("SWP 3$");
  3112. CONTROL FI;
  3113. CONTROL FI;
  3114. CONTROL IFEQ ECSCODE,1;
  3115. CONTROL IFEQ METERING,1;
  3116. INSTRMNT1(INSTST"SWPE");
  3117. CONTROL FI;
  3118. P&lt;MOVFROM>=TASKADDR[CURTASK];
  3119. P&lt;MOVTO>=(CURUSSWPPAG-1)*SWAPLEN;
  3120. IF TASKSWPIN[CURTASK] THEN READECS(SWAPLEN,MOVTO,MOVFROM,TMP1);
  3121. ELSE WRITECS(SWAPLEN,MOVFROM,MOVTO,TMP1);
  3122. CONTROL IFGQ ECSERRMAX,0;
  3123. IF TMP1 NQ 0 THEN # ECS ERROR, RETRY OR KILL #
  3124. BEGIN
  3125. ECSERRORS=ECSERRORS+TMP1;
  3126. IF ECSERRORS GQ ECSERRMAX THEN
  3127. BEGIN
  3128. ECSDOWN=TRUE;
  3129. C&lt;22,6>STATUSMSG="EM OFF";
  3130. END
  3131. # FAULT OUT THIS PAGE TO PROTECT FUTURE USERS #
  3132. FORCEALLOC(SWAPGOOD,CURUSSWPPAG,NUMSWPBIT);
  3133. IF TMP1 GQ 3 AND TASKSWPIN[CURTASK] THEN CURUSVICTIM=TRUE;
  3134. IF NOT TASKSWPIN[CURTASK] THEN GOTO SWAPSTART;
  3135. END
  3136. CONTROL FI;
  3137. CONTROL IFLS ECSERRMAX,0;
  3138. IF TMP1 NQ 0 THEN MELT("ECS HARDWARE$");
  3139. CONTROL FI;
  3140. CONTROL FI;
  3141. END
  3142. ELSE # DISK SWAPPING #
  3143. BEGIN
  3144. TASKSWPFIL[CURTASK]=1+MOD(CURUSSWPPAG-1-NUMSWPECS,NUMSWPFET);
  3145. TASKSWPPRU[CURTASK]=1+(CURUSSWPPAG-1-NUMSWPECS)/NUMSWPFET*SWAPPRUS;
  3146. TRCBOTH("SWPDSK$",TASKSWPFIL[CURTASK]);
  3147. TRCDEC(TASKSWPPRU[CURTASK]);
  3148. CONTROL IFEQ METERING,1;
  3149. INSTRMNT1(INSTST"SWPD");
  3150. CONTROL FI;
  3151. WHYLE NOT SWPFETDONE[TASKSWPFIL[CURTASK]] DO SMFDLY;
  3152. TMP1=TASKSWPFIL[CURTASK]; # VALID TILL SMFRCL #
  3153. C&lt;0,6>TMP2="SMFSWP";
  3154. C&lt;6,1>TMP2=O"33"+TMP1-1;
  3155. P&lt;ANYFET>=LOC(SWPFET[TMP1]);
  3156. P&lt;MOVFROM>=TASKADDR[CURTASK];
  3157. MAKEFET(ANYFET,TMP2,MOVFROM,SWAPBUFLEN);
  3158. SWPFETR[TMP1]=TRUE;
  3159. SWPFETRR[TMP1]=TASKSWPPRU[CURTASK];
  3160. IF TASKSWPIN[CURTASK] THEN READ(ANYFET,0);
  3161. ELSE
  3162. BEGIN
  3163. SWPFETIN[TMP1]=SWPFETIN[TMP1]+SWAPLEN;
  3164. IF CURUSSWPPAG GR MAXSWPPAG THEN
  3165. BEGIN
  3166. MAXSWPPAG=CURUSSWPPAG;
  3167. SWPFETRR[TMP1]=LOC(DUMB);
  3168. WRITER(ANYFET,0);
  3169. END
  3170. ELSE REWRITR(ANYFET,0);
  3171. END
  3172. SMFRCL(ANYFET);
  3173. END
  3174.  
  3175. # ONCE TASKSWPNOW IS CLEARED, SWAP CANNOT DELAY ANYMORE #
  3176.  
  3177. TASKSWPNOW[CURTASK]=FALSE;
  3178. CONTROL IFEQ METERING,1;
  3179. TMP1=TIMEOFDAY-TASKTIME[CURTASK];
  3180. INSTRMNT2(INSTST"SWPTIM",TMP1);
  3181. CONTROL FI;
  3182. TASKTIME[CURTASK]=TIMEOFDAY;
  3183.  
  3184. IOEND # OF SWAP #
  3185. PAGE # USER/SYSTEM-STATE CHANGING CODE #
  3186.  
  3187.  
  3188. PROC PAUSE;
  3189. IOBEGIN(PAUSE)
  3190. #
  3191. ** PAUSE - INTERFACE TO EXECUTIVE TO START/END TIME SLICE.
  3192. *
  3193. * PAUSE IS THE ROUTINE USED BY USER-MODE ROUTINES TO END A
  3194. * SLICE ON THE CPU, AND BY THE EXECUTIVE TO RESUME EXECUTION
  3195. * WHERE THE PREVIOUS TIME SLICE ENDED. THUS, PAUSE EXITS TO
  3196. * LABEL AFTERSLICE AND PROVIDES THE LABEL RESUME, WHICH
  3197. * RUNJOBS WILL JUMP TO JUST IN FRONT OF THE DEFINITION OF THE
  3198. * AFTERSLICE LABEL.
  3199. #
  3200. XDEF LABEL RESUME;
  3201. XREF LABEL AFTERSLICE;
  3202. GOTO AFTERSLICE;
  3203.  
  3204. RESUME: # HERE FOR NEW TIMESLICE #
  3205.  
  3206. IOEND # OF PAUSE #
  3207.  
  3208.  
  3209. PROC TRANSACT;
  3210. BEGIN
  3211. #
  3212. ** TRANSACT - TRANSITION FROM EXECUTIVE TO USER FOR SWAPIN.
  3213. *
  3214. * TRANSACT IS USED BY THE RUNJOBS EXECUTIVE, JUST BEFORE
  3215. * RUNJOBS DEFINES THE AFTERTRANS LABEL, TO SWITCH FROM
  3216. * EXECUTIVE MODE TO USER MODE AND PERFORM SWAPINS. TRANSACT
  3217. * THEN REPAIRS THE COMMON BLOCK DISPATCHING AREA, REPAIRS THE
  3218. * RETURN JUMP WORDS IN ALL ACTIVE SUBROUTINE ENTRY POINTS,
  3219. * CHECKS FOR CERTAIN INTERRUPT CONDITIONS, AND EXITS VIA A
  3220. * JUMP TO THE MORETRANS LABEL IN THE ENDTRANS ROUTINE. THIS
  3221. * TYPE OF EXIT IS USED BECAUSE THE TASK IS PRESUMED TO HAVE
  3222. * HAVE COMPLETED ITS PREVIOUS SWAPPED-IN TRANSACTION BY
  3223. * CALLING ENDTRANS, AND ENDTRANS IS RESUMED TO HAVE JUMPED TO
  3224. * THE EXECUTIVE JUST IN FRONT OF THE DEFINITION OF LABEL
  3225. * MORETRANS.
  3226. *
  3227. * ENTRY MAY BE CALLED ONLY BY RUNJOBS TRANSACTION SECTION.
  3228. * CURUSINTRPT - AN INTERRUPT MUST BE COMMUNICATED TO
  3229. * USER-MODE CODE AFTER SWAPIN IS COMPLETE.
  3230. * SHUTDOWN - CAUSES SYNTHESIS OF INTERRUPTS.
  3231. * CURUSRCVRY - FSE JOB DETACHING.
  3232. * RSTKPTR - SIZE OF REENTRANCY STACK.
  3233. *
  3234. * EXIT VIA LABEL MORETRANS.
  3235. * RENTSTK - REENTRANCY STACK.
  3236. * COMMON BLOCK AND SUBROUTINE ENTRIES REBUILT.
  3237. * USRBRK - 1 IF ANY INTERRUPT PASSED TO USER.
  3238. * CURUSVICTIM - TRUE IF SWAPIN RUINED USER DATA.
  3239. * FORCESINGLE, FORCENULL - ADDITIONAL INTERRUPTS.
  3240. * WORKFILE CHECKPOINTED AND EXIT VIA LABEL AFTEREDIT
  3241. * IF CURUSRCVRY IS ON.
  3242. *
  3243. * CALLS SWAP, DEALLOC, GETCOMMON, CHECKIO, MOVEWD, SPREAD.
  3244. *
  3245. * USES SWAPRSTK, TASKSWPIN[CURTASK].
  3246. #
  3247. XREF LABEL AFTEREDIT;
  3248. XREF LABEL AFTERTRANS;
  3249. XREF LABEL MORETRANS;
  3250.  
  3251. TRCSTR("NTR TRNSCT$");
  3252. TASKSWPIN[CURTASK]=TRUE;
  3253.  
  3254. SWAP;
  3255. # ONCE SWAP RETURNS, WE CANNOT REENTER UNTIL AFTER GETCOMMON #
  3256. IF SHUTDOWN NQ 2 THEN DEALLOC(SWAPBITS,CURUSSWPPAG,NUMSWPBIT);
  3257. CURUSSWPPAG=0;
  3258. LASTTASK=0; # RECONSTRUCT COMMON AFTER SWAP #
  3259. GETCOMMON;
  3260. # END OF TIME-CRITICAL SEQUENCE #
  3261.  
  3262. IF CURUSINTRPT THEN USRBRK=1;
  3263. IF CURUSVICTIM THEN
  3264. BEGIN
  3265. SMFVICTIM=TRUE;
  3266. ERRSTRING="ECS HARDWARE$";
  3267. END
  3268. IF SHUTDOWN NQ 0 THEN FORCESINGLE=TRUE;
  3269. IF SHUTDOWN GR 1 THEN
  3270. BEGIN
  3271. CURUSINTRPT=TRUE;
  3272. USRBRK=1;
  3273. FORCENULL=TRUE;
  3274. END
  3275. IF CURUSRCVRY THEN # CHKPT AND END EDIT #
  3276. BEGIN
  3277. FORCENULL=TRUE;
  3278. IF SHUTDOWN EQ 2 THEN
  3279. BEGIN
  3280. USRBRK=0;
  3281. CURUSINTRPT=FALSE;
  3282. END
  3283. IF NOT CURUSDONE THEN
  3284. BEGIN # IF WORKFILE NOT YET CHECKPOINTED #
  3285. CHECKIO; # CHECKPOINT WORKFILE #
  3286. END
  3287. GOTO AFTEREDIT;
  3288. END
  3289. MOVEWD(RSTKPTR-1,SWAPRSTK,RENTSTK);
  3290. SPREAD(RSTKPTR,RENTSTK);
  3291.  
  3292. # OUR RETURN GOES NOT TO CALLER BUT TO USER #
  3293. GOTO MORETRANS; # LET GATHERED CODE RETURN TO USER #
  3294.  
  3295. END # OF TRANSACT #
  3296.  
  3297.  
  3298. PROC ENDTRANS;
  3299. IOBEGIN(ENDTRANS)
  3300. #
  3301. ** ENDTRANS - END A TRANSACTION WITH SWAPOUT.
  3302. *
  3303. * ENDTRANS IS CALLED ONLY BY TTOTRAP, FOR THE PURPOSE OF
  3304. * SWAPPING THE CURRENT TASK OUT. ENDTRANS CONSOLIDATES DATA
  3305. * FROM SUBROUTINE ENTRY POINTS AND FROM THE DISPATCHABLE
  3306. * COMMON BLOCK, THEN SWAPS THE MEMORY IMAGE OUT. ENDTRANS
  3307. * THEN EXITS BY JUMPING TO LABEL AFTERTRANS IN THE RUNJOBS
  3308. * EXECUTIVE. ENDTRANS PROVIDES THE DEFINITION OF LABEL
  3309. * MORETRANS SO THAT WHEN RUNJOBS CALLS TRANSACT TO SWAP THIS
  3310. * USER BACK IN, TRANSACT CAN JUMP TO THE ADDRESS AT WHICH THE
  3311. * TASK HAD FORFEITED CONTROL.
  3312. *
  3313. * ENDTRANS IS ALLOWED TO BE CALLED ONLY BY TTOTRAP BECAUSE
  3314. * THE TASK CANNOT SWAPOUT WITH ANY RESIDUAL OUTPUT LEFT IN
  3315. * THE BUFFER OWNED BY THE TASK.
  3316. *
  3317. * ENTRY ONLY FROM TTOTRAP.
  3318. * RSTKPTR - DEPTH OF REENTRANCY STACK.
  3319. * RENTSTK - THE REENTRANCY STACK.
  3320. *
  3321. * EXIT VIA LABEL AFTERTRANS.
  3322. *
  3323. * CALLS GATHER, MOVEWD, PUTCOMMON, SWAP, MELT.
  3324. *
  3325. * USES SWAPRSTK, TASKSWPIN[CURTASK].
  3326. #
  3327. XREF LABEL AFTERTRANS;
  3328. XDEF LABEL MORETRANS;
  3329.  
  3330. TRCSTR("NTR NDTRNS$");
  3331. GATHER(RSTKPTR,RENTSTK);
  3332. MOVEWD(RSTKPTR-1,RENTSTK,SWAPRSTK);
  3333.  
  3334. # MUST EXECUTE INSTANTLY FROM PUTCOMMON INTO START OF SWAP #
  3335. PUTCOMMON; # MAKE COMMON SWAPPABLE #
  3336. TASKSWPIN[CURTASK]=FALSE;
  3337. SWAP;
  3338. # END OF TIME-CRITICAL SEQUENCE #
  3339.  
  3340. CONTROL IFGQ PARANOIA,3;
  3341. IF TASKNXTTTO[CURTASK] NQ 0 THEN MELT("NTRNS 2$");
  3342. CONTROL FI;
  3343. GOTO AFTERTRANS;
  3344.  
  3345. # RETURN GOES BACK TO USER #
  3346. MORETRANS:
  3347.  
  3348. IOEND # OF ENDTRANS #
  3349. PAGE # INITIALIZATION AND TERMINATION #
  3350.  
  3351.  
  3352. PROC INITMON;
  3353. BEGIN
  3354. #
  3355. ** INITMON - INITIALIZE SMFEX.
  3356. *
  3357. * INITMON IS THE PRESET ROUTINE FOR SMFEX. THE FOLLOWING
  3358. * FUNCTIONS ARE PERFORMED --
  3359. *
  3360. * THE PARAMETERS CRACKED BY THE OPERATING SYSTEM AT RA+2 ARE
  3361. * CHECKED FOR RECOVERY MODE OR FOR A NUMBER OF TASKS TO BE
  3362. * FORMATTED. THE SHUTDOWN FLAG IS SET FOR RECOVERY MODE, AND
  3363. * THE TASKSAVAIL FLAG IS SET AND FORCED WITHIN REASONABLE
  3364. * BOUNDS FOR A NUMERIC PARAMETER.
  3365. *
  3366. * MISCELLANEOUS POINTERS AND LENGTH FIELDS ARE COMPUTED. THE
  3367. * FIELD LENGTH IS THEN INCREASED TO MAKE ROOM FOR THE MODEL
  3368. * FORMAT OF THE COMMON BLOCK. THE FIELD LENGTH IS INCREASED
  3369. * TO ALLOCATE THE TERMINAL INPUT BUFFERS. THE BITMAPS USED
  3370. * FOR ALLOCATION OF SMFEX RESOURCES ARE INITIALIZED. THEN
  3371. * EACH TASK IS BUILT OUT OF INCREASED FIELD LENGTH.
  3372. *
  3373. * TASK CONSTRUCTION IS DELEGATED TO THE BUILDTASK ROUTINE.
  3374. * THE COMMON BLOCK IS USED TO CONSTRUCT THIS TASK'S POINTERS
  3375. * FOR A NUMBER OF PER-TASK ARRAYS. THEN COMMON BLOCK IS THEN
  3376. * COPIED INTO THE EXTENDED FIELD LENGTH SO EACH TASK CAN
  3377. * CONTAIN ITS OWN BASE ADDRESSES FOR ARRAYS.
  3378. *
  3379. * THE EXTENDED MEMORY FIELD LENGTH IS DETERMINED BY SEEING
  3380. * HOW MUCH MEMORY IS DESIRED FOR THE COMPILE-TIME
  3381. * CONFIGURATION AND HOW MUCH IS ACTUALLY AVAILABLE FROM THE
  3382. * RUNNING SYSTEM. THE ALLOCATION BITMAPS ARE MODIFIED IF
  3383. * NEEDED TO ALLOW FOR THE NUMBER OF ECS SWAP PAGES ACTUALLY
  3384. * OBTAINED. EXTENDED MEMORY SWAPPING IS COMPLETELY DISABLED
  3385. * IF THE RUNNING SYSTEM CANNOT PROVIDE ANY SECONDARY FIELD
  3386. * LENGTH AT ALL.
  3387. *
  3388. * FOR SUBSYSTEM RECOVERY, A SHORTENED INITMON ALGORITHM TAKES
  3389. * EFFECT. WE ASSUME THE PREVIOUS SMFEX JOB STEP EXECUTED AN
  3390. * IDENTICAL VERSION OF THIS PROGRAM (I.E., SMFEX HAS NOT BEEN
  3391. * SYSEDITED WHILE RUNNING) AND THAT THE TERMINATION OF THE
  3392. * PREVIOUS SMFEX JOB STEP EXITED INTO A "DMB" FORMAT DUMP
  3393. * FILE. THE DUMP FILE IS SCANNED TO OBTAIN THE USER TABLE.
  3394. * WE CHECK ALL USER TABLE ENTRIES FOR RECOVERABLE TASKS AND
  3395. * QUEUE THOSE USERS FOR SWAPIN. RECOVERABLE TASKS ARE THOSE
  3396. * WHICH EXIST ON A SWAP PAGE BUT NOT IN MEMORY. FOR
  3397. * SUBSYSTEM RECOVERY, THE INITMON ALGORITHM TERMINATES AT
  3398. * THIS POINT IN THE FLOW.
  3399. *
  3400. * FOR TRUE SUBSYSTEM INITIATION, THE REMAINDER OF THE INITMON
  3401. * ALGORITHM IS AS FOLLOWS --
  3402. *
  3403. * ALL DISK SWAP FILES ARE EVICTED.
  3404. *
  3405. * THE NEGATIVE FIELD LENGTH IS BOOSTED TO ITS ANTICIPATED
  3406. * HIGH WATER MARK BY ALLOCATING THEN RETURNING A LARGE GROUP
  3407. * OF TOKEN FILES. THIS IS DONE BECAUSE THE TLX PP ROUTINE
  3408. * WHICH TRANSITIONS USERS FROM SINGLE USER MODE TO MULTI USER
  3409. * MODE IS UNABLE TO INCREASE OUR NEGATIVE FIELD LENGTH TO
  3410. * MAKE ROOM FOR LOCAL FNT'S FOR THE TRANSFERRED WORKFILES.
  3411. * TLX TREATS OUR PRE-ALLOCATED NEGATIVE FIELD LENGTH AS A
  3412. * LIMITATION AS TO WHETHER A PARTICULAR SINGLE USER EDITOR
  3413. * JOB WILL BE ACCEPTED INTO MULTI USER MODE.
  3414. *
  3415. * FINALLY, COMMUNICATIONS ARE ESTABLISHED WITH IAFEX VIA THE
  3416. * SCP/UCP FACILITY. SMFEX IS THE UCP AND IAFEX IS THE SCP.
  3417. #
  3418. ITEM TMP1,TMP2,TMP3,TMP4;
  3419.  
  3420. P&lt;CORE>=0;
  3421. IF B&lt;00,01>MEM[CSMR] EQ 0 THEN # IF SYSTEM CHARACTER SET = 63 #
  3422. BEGIN
  3423. XLTINTXP[O"00"]=O"4045"; # COLON = PERCENT #
  3424. XLTINTXP[O"63"]=O"4072"; # PERCENT = COLON #
  3425. XLTDSPXP[O"00"]=O"4045"; # COLON = PERCENT #
  3426. XLTDSPXP[O"63"]=O"4072"; # PERCENT = COLON #
  3427. XLTDSPINT[O"00"]=O"0063"; # COLON = PERCENT #
  3428. XLTDSPINT[O"63"]=O"0000"; # PERCENT = COLON #
  3429. XLTXPINT[O"45"]=O"0000"; # PERCENT = COLON #
  3430. XLTXPINT[O"72"]=O"0063"; # COLON = PERCENT #
  3431. XLTINTDSP[O"00"]=O"0055"; # COLON = BLANK #
  3432. END
  3433.  
  3434. SFMCSTF;
  3435.  
  3436. IF C&lt;0,7>MEM[2] EQ "RECOVER" THEN SHUTDOWN=2;
  3437. ELSE
  3438. BEGIN
  3439. TMP1=0;
  3440. TMP2=0;
  3441. TMP3=C&lt;0,1>MEM[2]-O"33";
  3442. WHYLE TMP2 LQ 6 AND TMP3 GQ 0 AND TMP3 LQ 9 DO
  3443. BEGIN
  3444. TMP1=TMP1*10+TMP3;
  3445. TMP2=TMP2+1;
  3446. TMP3=C&lt;TMP2,1>MEM[2]-O"33";
  3447. END
  3448. IF TMP1 GQ 2 AND TMP1 LQ NUMTASKS THEN TASKSAVAIL=TMP1;
  3449. END
  3450.  
  3451. P&lt;SWAPMASK>=LOC(SWAPGOOD);
  3452. SWAPLEN=LOC(SWAPEND)-LOC(DATASTART);
  3453. DISPATLEN=LOC(DISPATEND)-LOC(DATASTART);
  3454. FIELDLEN=B&lt;42,18>MEM[O"65"];
  3455. MODELPTR=FIELDLEN;
  3456. MODELLEN=LOC(SWAPEND)-LOC(DATAEND);
  3457. FIELDLEN=MODELPTR+MODELLEN;
  3458. FLDLEN(FIELDLEN+4);
  3459. P&lt;MOVTO>=MODELPTR;
  3460. MOVEWD(MODELLEN,DATAEND,MOVTO);
  3461. FOR TMP3=1 STEP 1 UNTIL NUMTTIBUF DO
  3462. BEGIN
  3463. TTIBUFADDR[TMP3]=FIELDLEN;
  3464. FIELDLEN=FIELDLEN+SIZTTIBUF;
  3465. FLDLEN(FIELDLEN+4);
  3466. END
  3467. FOR TMP1=1 STEP 1 UNTIL MAXREENT DO RSTK[TMP1]=LOC(RSTK[TMP1]);
  3468. INITBITMAP(SWAPBITS,NUMSWPBIT,NUMSWPECS+NUMSWPDSK);
  3469. INITBITMAP(TTIBITS,NUMTTIBIT,NUMTTIBUF);
  3470. INITBITMAP(SWAPGOOD,NUMSWPBIT,NUMSWPECS+NUMSWPDSK);
  3471. INITBITMAP(SWAPBAD,NUMSWPBIT,NUMSWPECS+NUMSWPDSK);
  3472. INITBITMAP(TTIGOOD,NUMTTIBIT,NUMTTIBUF);
  3473. KILLECSBITS(SWAPBAD);
  3474. MEM[USRBASE]=LOC(USERTAB); # FOR EASY C DISPLAY #
  3475. MEM[SLTBASE]=LOC(TASKTAB);
  3476. CONTROL IFEQ METERING,1;
  3477. MEM[STTBASE]=LOC(INSTDATA);
  3478. CONTROL FI;
  3479. FOR CURTASK=1 STEP 1 UNTIL TASKSAVAIL DO BUILDTASK(CURTASK);
  3480. SWAPLEN=SWAPLEN+TASKDSPADR[1]-TASKADDR[1];
  3481. SWAPPRUS=((SWAPLEN+O"100")/O"100");
  3482. SWAPBUFLEN=1+SWAPPRUS*O"100";
  3483. FLDLEN(FIELDLEN+4);
  3484.  
  3485. CONTROL IFEQ ECSCODE,1;
  3486. # REQUEST ECS FIELD LENGTH/ SEE IF IT IS THERE #
  3487. GETFLCE(ECSFIELD); # GET VALIDATION LIMIT #
  3488. TESTECS(TMP1); # GET EXISTENCE/ENABLED #
  3489. IF B&lt;0,12>ECSFIELD NQ 0 AND TMP1 NQ 0 THEN
  3490. BEGIN
  3491. # ALLOCATE DESIRED OR AVAILABLE ECS FIELD LENGTH #
  3492. ECSFIELD=MIN(NUMSWPECS*SWAPLEN,512*B<0,12>ECSFIELD);
  3493. FLDLENE(ECSFIELD);
  3494. SETRFLE((ECSFIELD+511)/512);
  3495. PROTEON; # SINCE ABORT RECOVERY ADVANCES #
  3496. # TURN OFF ANY SWAP PAGES BEYOND AVAILABLE FIELD LENGTH #
  3497. TMP1=ECSFIELD/SWAPLEN;
  3498. FOR TMP2=TMP1+1 STEP 1 UNTIL NUMSWPECS
  3499. DO FORCEALLOC(SWAPGOOD,TMP2,NUMSWPBIT);
  3500. END
  3501. ELSE KILLECSBITS(SWAPGOOD); # TURN OFF ALL ECS SWAP PAGES #
  3502. CONTROL FI;
  3503. CONTROL IFEQ ECSCODE,0;
  3504. KILLECSBITS(SWAPGOOD);
  3505. CONTROL FI;
  3506.  
  3507. IF SHUTDOWN EQ 2 THEN
  3508. BEGIN
  3509. TERMMON; # SHUT OFF ANY INPUT #
  3510. P&lt;MOVFROM>=FIELDLEN;
  3511. MAKEFET(DMBFET,"ZZZZDMB",MOVFROM,O"1001");
  3512. FIELDLEN=FIELDLEN+O"1001";
  3513. FLDLEN(FIELDLEN+4);
  3514. REWIND(DMBFET,1);
  3515. READ(DMBFET,0);
  3516. TMP1=0;
  3517. TMP4=0;
  3518. FOR TMP2=0 STEP 1 UNTIL O"61" DO
  3519. BEGIN # UNTIL RIGHT (CM) CONTROL WORD #
  3520. READO(DMBFET,TMP1,TMP4); # ACCESS NEXT CONTROL WORD #
  3521. IF TMP4 NQ 0 THEN MELT("RCVR 1$");
  3522. END
  3523. IF C&lt;0,2>TMP1 NQ "CM" THEN MELT("RCVR 2$");
  3524. FOR TMP2=1 STEP 1 UNTIL LOC(USERTAB) DO
  3525. BEGIN # CONSUME LOWER FIELD LENGTH #
  3526. READO(DMBFET,TMP1,TMP4);
  3527. IF TMP4 NQ 0 THEN MELT("RCVR 3$");
  3528. END
  3529. # FINALLY READ IN THE USER TABLE #
  3530. FOR TMP2=1 STEP 1 UNTIL 3*NUMSMFUSR DO
  3531. BEGIN
  3532. P&lt;MOVTO>=LOC(USERTAB)+TMP2-1;
  3533. READO(DMBFET,MOVTO,TMP4);
  3534. IF TMP4 NQ 0 THEN MELT("RCVR 4$");
  3535. END
  3536. REWIND(DMBFET,1); # IN CASE TAKE ANOTHER DUMP #
  3537. FOR CURUSER=1 STEP 1 UNTIL NUMSMFUSR DO
  3538. BEGIN # UPDATE AND QUEUE CHECKPT #
  3539. GETUSER;
  3540. IF CURUSINTASK THEN CURUSDONE=TRUE;
  3541. CURUSINQUE=FALSE;
  3542. CURUSTTIBUF=0;
  3543. CURUSQUELNK=0;
  3544. CURUSINTASK=FALSE;
  3545. IF CURUSLOGGED AND CURUSSWPPAG NQ 0 AND NOT CURUSDONE THEN
  3546. BEGIN
  3547. TRCBOTH("RECOVER$",CURUSER);
  3548. CURUSRCVRY=TRUE;
  3549. CURUSINTRPT=TRUE;
  3550. PUTINQ;
  3551. END
  3552. PUTUSER;
  3553. END
  3554. FOR TMP1=1 STEP 1 UNTIL NUMSWPFET DO SWPFETDONE[TMP1]=TRUE;
  3555. TRCSTR("END INITMON RCVR$");
  3556. RETURN; # SO THAT NOTHING ELSE IS DONE #
  3557. END
  3558.  
  3559. FOR TMP1=1 STEP 1 UNTIL NUMSWPFET DO
  3560. BEGIN
  3561. CONTROL IFGR NUMSWPFET,8; BADSTUFF; CONTROL FI; # CODE DEPENDENT #
  3562. C&lt;0,6>TMP2="SMFSWP";
  3563. C&lt;6,1>TMP2=TMP1+O"32";
  3564. P&lt;ANYFET>=LOC(SWPFET[TMP1]);
  3565. P&lt;MOVFROM>=TASKADDR[1];
  3566. MAKEFET(ANYFET,TMP2,MOVFROM,SWAPBUFLEN);
  3567. READ(ANYFET,1); # ASSURE FNT ALLOCATE #
  3568. EVICT(ANYFET,1); # ASSURE NO OLD DATA #
  3569. END
  3570.  
  3571.  
  3572. PROC GENNULL;
  3573. BEGIN
  3574. C&lt;0,2>TMP2="NE";
  3575. TMP3=TMP1;
  3576. FOR TMP4=6 STEP -1 UNTIL 2 DO
  3577. BEGIN
  3578. C&lt;TMP4,1>TMP2=O"33"+MOD(TMP3,10);
  3579. TMP3=TMP3/10;
  3580. END
  3581. MAKEFET(NULLFET,TMP2,CORE,O"101");
  3582. END # OF GENNULL #
  3583.  
  3584.  
  3585. FOR TMP1=1 STEP 1 UNTIL NUMSMFUSR DO
  3586. BEGIN # MANY NULL FILES TO ENLARGEN NFL #
  3587. GENNULL;
  3588. READ(NULLFET,1); # ASSURE FNT ALLOCATE #
  3589. END
  3590. FOR TMP1=1 STEP 1 UNTIL NUMSMFUSR DO
  3591. BEGIN # THEN RELEASE THE FNT SPACE #
  3592. GENNULL;
  3593. RETERN(NULLFET,1);
  3594. END
  3595. IAFPTR=LOC(SSCINP[0]);
  3596. INITSSCWORD[1]=IAFHEADER;
  3597.  
  3598. P&lt;SSCBUFFER>=LOC(INITSSC);
  3599. SSCSTATUS=-1;
  3600. # DELAY UNTIL IAF HANDSHAKE WORKS OR IDLE COMMAND DETECTED #
  3601. WHYLE SSCSTATUS LAN O"7776" NQ 0 AND MEM[0] LAN O"100000" EQ 0 DO
  3602. BEGIN
  3603. SSCWORD=O"0000 0000 0000 0103 0000";
  3604. SYSREQ("SSC",0,LOC(SSCBUFFER),IAFSSID);
  3605. RECALL(0);
  3606. END
  3607.  
  3608. SFMSSTF;
  3609. TRCSTR("END INITMON$");
  3610.  
  3611. END # OF INITMON #
  3612.  
  3613.  
  3614. PROC TERMMON;
  3615. BEGIN
  3616. #
  3617. ** TERMMON - TERMINATE SMFEX NORMALLY.
  3618. *
  3619. * CALLS SFMCSTF.
  3620. #
  3621. SFMCSTF;
  3622. TRCSTR("COMPLETE$");
  3623. TRCFRC;
  3624. END # OF TERMMON #
  3625.  
  3626.  
  3627. PROC MELT(STR);
  3628. BEGIN
  3629. #
  3630. ** MELT - TERMINATE SMFEX ABNORMALLY.
  3631. *
  3632. * ENTRY STR - ERROR MESSAGE FOR INTERNAL ABORT CONDITION.
  3633. * COMPLETE - IF ALREADY SET, THEN MELT FUNCTIONS AS
  3634. * AN INTERFACE TO PRODUCE A DAYFILE MESSAGE THEN
  3635. * ALLOW NORMAL TERMINATION. NORMALLY, COMPLETE
  3636. * IS FALSE AND MELT ABORTS THE JOB STEP.
  3637. *
  3638. * EXIT VIA LABELS ABORT OR ENDRUN.
  3639. *
  3640. * CALLS MESSAGE, TERMMON.
  3641. #
  3642. ITEM STR C(30);
  3643. ITEM STR2 C(30);
  3644. ITEM TMP1,TMP2;
  3645.  
  3646. TRCSTR(STR);
  3647. TRCFRC;
  3648. STR2=STR;
  3649. TMP2=0;
  3650. FOR TMP1=0 STEP 1 UNTIL 29 DO
  3651. BEGIN
  3652. IF TMP2 EQ 0 AND C&lt;TMP1,1>STR2 EQ "$" THEN TMP2=TMP1+1;
  3653. END
  3654. FOR TMP1=29 STEP -1 UNTIL TMP2 DO C&lt;TMP1,1>STR2=0;
  3655. MESSAGE(STR2,0,1);
  3656. TERMMON;
  3657. IF COMPLETE THEN ENDRUN;
  3658. ELSE ABORT;
  3659.  
  3660. END # OF MELT #
  3661. PAGE
  3662.  
  3663. #
  3664. ** SMFEX - MAIN ALGORITHM.
  3665. *
  3666. * THE SMFEX MAIN ALGORITHM INITIALIZES THE SUBSYSTEM, THEN
  3667. * LOOPS ON THE THREE MAIN PROCESSES UNTIL A COMPLETION FLAG
  3668. * IS DETECTED. THE SUBSYSTEM IS THEN TERMINATED.
  3669. *
  3670. * THE THREE PROCESSING PHASES PERFORM TIME-DEPENDENT FUNCTIONS,
  3671. * RECEIVE AND QUEUE MESSAGES FROM IAFEX, AND EXECUTE TASKS AND
  3672. * REPLY TO IAFEX.
  3673. *
  3674. * CALLS INITMON, DOTIMER, DOINPUT, RUNJOBS, INITMON.
  3675. #
  3676. ITEM TMP1;
  3677.  
  3678. INITMON; # GET EVERYTHING SET UP #
  3679.  
  3680. WHYLE NOT COMPLETE DO # MAIN LOOP #
  3681. BEGIN
  3682. DOTIMER; # RECALL CPU, HANDLE TIMER AND OPERATOR #
  3683. DOINPUT; # PROCESS INPUT FROM IAFEX #
  3684. RUNJOBS; # EXECUTE ANY TASKS THAT CAN #
  3685. END # OF MAIN LOOP #
  3686.  
  3687. TERMMON; # CLOSE UP SHOP #
  3688. ENDRUN;
  3689.  
  3690.  
  3691. END TERM