APPENDIX 1 USER MANUAL FOR THE FIRST SYSTEM
USER MANUAL FOR MUSS11 B. GILMORE JUNE 1975
CONTENTS TITLE PAGE General features 3 Compiling a program. 4 Running a program. 5 External routines. 6 Input and output to terminals 7 Running PAL11F programs. 8 Operator control of the system. 9 Device handlers. 13 UTILITY PROGRAMS Editor. 15 File transfer program. 16 File Name program 18 Archive program. 20 EXTERNAL ROUTINE LIBRARY WAIT 22 NAME 22 DEFN 22 WRIT 22 COM 23 DA 23 FIDENT 24 RENAME 24
GENERAL FEATURES OF MUSS11 Muss11 is a system designed to allow multi programming and multi user access to PDP11S without memory management. It is a general purpose system that has the capability of running in a real-time environment. Although it will run on any member of the PDP11 family, it will not take advantage of the memory management/protection features of the larger machines. A disc, or other form of mass storage, is desirable, but is not a necessity. The system will multi-program up to 128 separate programs, running on one, or a number of terminals. All programs are core resident and may run at one of eight priorities - corresponding to the eight machine priorities, although for normal programs, only the bottom four are used. As a rule programs are written in IMP, but .pal11f programs can be run with certain restrictions (the restrictions are listed later). When the system is running, the highest priority program able to run is given the CPU. If there are several programs of equal priority able to run, they are time sliced at not more than 20 milliseconds each. The priority structure ensures that the system can be used in a real-time environment when very fast responses to interrupts are required. A program may dynamically change its priority up or down in time critical areas to ensure response. Sections of code on the system may be shared between users, thereby cutting down on the total amount of core required. For example, several users may use the editor, each having his own private storage but sharing one copy of the editor code. An ASSEMBLER (to stand-alone PAL11F standards) is available for systems with at least 16k words of store, and it is hoped to provide an IMP compiler on systems with 28k words within the next few months. Alternativly programs can be written, compiled and assembled on EMAS, then the binary is loaded on the system.
COMPILING AN IMP PROGRAM The Imp program should be compiled and assembled on EMAS (for full details of the language and how to run it see documentation by K. Yarwood ERCC (ext. 2636) - for the assembler see B. Gilmore ERCC (ext. 2636). 1) A program requires a short header to inform the system of its starting address, priority, name etc. The format is (as added into the IMP program):- *ENDCO ; !This is the overall length of the code *.ASCII /xxxx/; !4 character program name *0 ; !'subsystem' number (0 is default) *MAIN+10 ; !starting address (MAIN is a label ; ! defined by the compiler) *40 ; !priority to run at:- ! 0 - Priority level 0 ! 40 - Priority level 1 ! 100 - Priority level 2 ! 140 - Priority level 3 *0 ; !descriptor length (0 is default) *2000 ; !stack length ( = space for arrays + 1000 octal) e.g. *ENDCO *.ASCII /SORT/ *0,MAIN+10,40,0,2000 2) A control statement is required to force the compiler to 1) Produce POSITION INDEPENDANT CODE (%CONTROL 8) 2) Special code for MUSS11 (%CONTROL 8192). This control value effects the code dumped for EXTERNALS, REALS and STRINGS. This should be put before the %BEGIN %CONTROL 8200 %BEGIN The %CONTROL statement may be expressed in either octal or Hex in the standard format, e.g. %CONTROL 8200 may be written %CONTROL 0'20010' or %CONTROL X'2008'. The standard bits for setting checks on or off may also be used, for a full list see Appendix one. The more useful ones are:- 1) Line number updating (%CONTROL 1)
2) Array bound checking (%CONTROL 4). Summary: use %CONTROL 0'20015' for checks ON %CONTROL 0'20010' for checks OFF The header for an external routine/fn/map is different and is explained in the section 'using external routines'. RUNNING THE PROGRAM The Binary output from the assembler may be 1) punched on tape, 2) punched on cards or 3) sent to the relevant remote. For tape and cards, the program 'BINY' is used to load the tape/cards to the disc, 'TRANY' is used when a file comes off the line. These two programs are discribed in the section of utility programs. The file on disc is then 'RUN' - by using the operator command 'RU' in 'OIT' (see command A1 under operator commands). This command instructs the loader to load the file into core, then to set up a system descripter (PSECT) and tell the system to enter it. The 'sub-system' will then grab space for the programs stack, setting up its 'R1' and its 'SP' and then entering the program at the starting address and priority described in the header. If the program executes correctly (or has a standard IMP fault) then the message 'STOPPED AT LINE x MIN STK xxxxxx' is output and the program is completely purged from core. (The message 'MIN STK xxxxx' refers to the minum stack the program had while it is executing - this is tied up with the parameter specified on the header). On the other hand if the program causes an address error or an illegal instruction, then :- XXXX TASK ERROR! is output. The program in this case is not purged from core, allow the cause of the fault to be determined, and so must be allowed to go by giving the command 'PU XXXX' (see operators command A7). (XXXX is its program name).
Using External Routines 1) PRINT and READF (real read), if required, should be declared as external routine at the top of the program. %EXTERNALROUTINESPEC PRINT(%REAL X, %INTEGER A,B) %EXTERNALROUTINESPEC READF(%REALNAME X) 2) To create a new external routine file. 1) only one external routine per file is allowed. 2) compile with normal control options. 3) use the following header (example uses %EXTERNALROUTINE ABCDEF) *ENDCO-. *.ASCII /ABCD/ 0,ABCDEF,<PRIORITY>,0 ( or 0,16,40,0) %CONTROL X'2008' %EXTERNALROUTINE ABCDEF(%INTEGER A,B,C) %END %ENDOFFILE 3) The routine should be put in a file named ABCDYY (if the name is less than 4 characters then pad out with Y's e.g. AYYYYY).
INPUT AND OUTPUT TO TERMINALS In general on MUSS11 all input/output is line orientated, ie a program receives an entire line of input at once, and nothing is actually output until the program issues a newline (or SELECT OUTPUT). However as the PDP11 version of the IMP compiler does not cater for PROMPS in the EMAS sense, the general effect can be obtained by using 'PRINTSYMBOL(0)'. PRINTSYMBOL(0) executed by a program will immediately send the current line to the output device - without a terminating newline. The zero character is not printed. For example, if %PRINTTEXT'DATA:'; PRINTSYMBOL(0) is used in a program outputting to the teletype, it will output the 'DATA:', leaving the carriage positioned past it; the user can then type a reply on the same line. However it will not repeat itself if the user types a newline and the program still requires data. The program MUST re-issue the message. It is perfectly reasonable to have two or more programs outputting to the same teletype. Complete lines from each program will be generated and will appear on the device, the lines alternating between each program. There is a problem however, in having two programs simultaneously inputting from one terminal. It will work, BUT one line of input will go alternately to each program and it will not always be possible to determine which program will get the next line of input.
RUNNING PAL11F PROGRAMS PAL11F programs may be run on the system if they conform to the following rules:- 1) They must be position independant. 2) The I/O must conform to MUSS11 I/O. For example, the TELETYPE must not be accessed directly, it can only be used by issuing the relevant SVC. 3) In most cases, because of the differences in I/O, a program written to run under DOS will not run under MUSS11 without a major re-write (as is the case in switching between DEC systems). If starting from the beginning, it will usually be easier to imbed the program in an IMP looking header (in assembler). In this manner it will be fairly easy to use the I/O facilities of IMP itself, while still allowing a fairly free use of ASSEMBLER. For further details please contact B. Gilmore.
OPERATOR CONTROL OF THE SYSTEM An operator can control the system by typing the sequence 'CTRL+R' (denoted as ^R) (which echoes OIT:) and a command. Notes: 1) only the first two characters of the command word need to be typed. 2) all parameters should be separated by at least one space. 3) the sequence is terminated by a CR. 4) a program's identifier may be used instead of its name. Commands:- A) Program control 1) RU(N) <filename> run a program 2) SU(SPEND) <prog name> suspend a program (when it is next awake) 3) CO(NTINUE) <prog name> allow a program to continue 4) KI(LL) <prog name> kill a program 5) LO(AD) <file name> load a program into core 6) ST(ART) <prog name> start up a previously loaded program 7) PU(RGE) <prog name> Remove a program from core after it has crashed. B) System information 1) PS(ECTS) list all the programs in the system 2) DU(MP) <from> <to> dump out an area of core 3) EX(AMINE) <prog name> dump out a program psect 4) MO(DIFY) <octal> examine a core location 5) NE(XT) examine the next core location 6) RE(PEAT) examine the location again 7) SC <word> <contents> Set a word in the communication area. C) Card reader control 1) CR ASC tell the card reader to read in ASCII mode 2) CR BIN tell the card reader to read in binary mode 3) CR EOT marks the end of a pack of cards.
DETAILED DESCRIPTION OF THE COMMANDS. A1) RUN <filename> The loader attempts to load the named file, create a descriptor for it (called a PSECT) and start it executing. 1) if the file does not exist (or the file is not in the correct format) then the message 'EOF!' is put out. 2) If it loads correctly, then the program name, address of the file and its system number is output:- PROG <address> <identifier> 3) If the loader is busy the 'OIT' types NO! 4) If there is no core the 'OIT' types 'NO CORE!' A2) SUSPEND <progname> A program may be temporarily halted in its execution to allow 1) the debugging program to be run 2) to wait for an operator to put a special (i.e. non-system) device on line. 3) before a program is killed. This command does not take effect until the program next has a chance to get the CPU. A3) CONTINUE <progname> This command is the converse of the suspend command, allowing the program to continue its execution. There are two main occasions this is used 1) after a 'SUSPEND' has been done 2) after a program/system test has issued the 'WAIT' SVC to wait for some operator action e.g. after cards have been put in the hopper, 'CO CR' is typed, or if the line printer was off-line - 'CO LP' is typed after it is put on-line. A4) KILL <prog name> A program may be aborted by Killing it.
The following sequence must be followed. 1) SU <prog> to get it to the 'wait state' 2) KI <prog> instruct the supervisor to kill it - the message:- n termination req. STOPPED AT LINE n MIN STK x is output and the program is removed from core A5) LOAD <file name> The command does the local phase of the 'Run' command. the loader replies: PROG <address> The error messages are as in run. This command may be used to load an external routine in order to put patches in the file before running the main program. A6) START <progname> This command is used to start up a previously loaded program, the loader outputs <identifier> A7) PURGE <progname> This command is used to remove a program from core after it has aborted with an address error or similar fault. B1) PSECTS This command lists the programs and system tasks in the format:- name address state name address state etc. B2) DUMP <from> <to> Areas of core (or device registers) may be dumped out, dumping
always starts from a 20 byte boundary. If an illegal address is specified the 'OUCH!' is output. A dump can be stopped by hitting ESC. B3) EXAMINE <prog name> The descriptor (PSECT) of a program (its state, prompts system variable, I/O definitions etc.) is dumped out. B4) MODIFY <address> A location (given in octal) may be examined and/or modified by using this command e.g. (system response is underlined) M0 1000 (CR) 001000 : 000001 : ^R 123456 (CR) > ^ If the location is not to be modified then the number is left out. Typing a dot will then examine the next location, the '>' will use the contents as the address for examine and ^ will go to the previous address. B5) NEXT This examines the next location, responses are the same as for examine. B6) REPEAT This repeats the last location. B7) Set Communication word. This command sets the word 'word' in the communication area to 'cont'. See EXTERNAL INTEGER MAP COM for details of its use. Card Reader Commands C1) CR ASC This command switches the mode of sending cards to ASCII (which is the default), it will take effect on the next card read.
C2) CR BIN Is similar to CR ASC but switches the mode to binary. C3) CR EOF This command tells the card reader handler to signal an 'end-of-file' to the program reading from it.
DEVICE HANDLERS 1) LINE PRINTER The system task which handles the line printer will assume it is on-line and ready. If it is not, or the printer stops (out of paper etc.) then the message:- LP OFFLINE! is output on the main teletype. The line printer should be put on-line, or fixed, then:- ^R CO LP (See operator command A3) is typed on any console. The message:- LP TASK ERROR! will appear if the device registers are removed or changed or if there is an error in the handler (rare!). 2) PAPER TAPE READER On IPL (initial program load), the tape reader will attempt to start up, the message:- PR OFFLINE! will be output if there is no tape (normal condition). This message is also output when the reader reaches the end of a tape. When a tape is to be read, it is put in the reader and ' ^R CO PR' is typed on any console. The reader should read a section of tape and will then be ready for use. 'PR TASK ERROR!' will be output for similar reasons as above. Note: an 'EOF' is assumed at the end of each tape. 3) CARD READER
This is similar to the paper tape reader with the difference in the End-of-file handling as described in operator commands C1, C2 and C3. 4) DISC AND DEC TAPE The messages:- DK OFFLINE! DF OFFLINE! DT OFFLINE! - are output if the relevant device is off line, or if there is a read/write error on a transfer.
UTILITY PROGRAMS A) EDITOR OBJECT FILE: EDITY This editor is a PDP11 version of the COMPATIBLE CONTEXT EDITOR which runs on EMAS, PDP15S and PDP8S. OPERATING PROCEDURE: When started, the editor prompts with:- EDIT VN.M # The user responds by typing the input and output file names in the form OUTPUT FILE NAME < INPUT FILE NAME or OUTPUT FILE NAME 1) If the input file does not exist, or is not specified, then a new file is created. 2) A temporary file is created, so, at the end of the editing session the 'old' output file is destroyed and the temporary file is renamed. 3) To edit a file to itself, the form FILE NAME < FILE NAME is used. 4) Editing commands are as in H. Dewar's 'Compatible Context Editor' with the following differences:- A) '%T' will close all the files then restart the EDITOR. B) The EDITOR operates with a 'window' of the file held in core, this will normally be transparent to the user, the command 'M-0' is an exception as it can only move to the top of the 'window'. C) No secondary stream is implemented.
B) FILE TRANSFER PROGRAM OBJECT FILE: TRANY This IMP program is a general file/file and file/peripheral transfer program, including transfers to and from a synchronous communications line in IMP 2780 protocol. OPERATING PROCEDURES: When TRAN is ready to accept a command it prompts:- TRAN: The format for the response is:- FILE/DEV < FILE/DEV,FILE/DEV or DIRECTIVE Where FILE/DEV is FILE NAME or DEVICE NAME A file name is defined as a group of alphanumeric characters with a length of one to six characters. 'DEVICE NAME' is defined as:- KB: (keyboard input) or TT: (teletype output) or LP: (line printer) or PR: (paper tape reader) or CR: (card reader) or RJ: (symchronous line) The following are legal directives: ST: - Stop TRAN. SI: - Force a signon to the remote machine. NS: - Start without a signon. EF: - Force an end-of-file to the remote machine. BI: - Do the transfer in BINARY mode. If a command is typed incorrectly, the message 'FORMAT?' is output and the prompt is re-issued. Using the form 'FILE/DEV,FILE/DEV' causes a concatenation of the two input streams into the output file or device.
SYNCHRONOUS LINE HANDLING 1) TRAN will normally sign-on automatically when the first reference to 'RJ:' is made, the message 'SIGNED ON' is output, then it obeys the request. 2) A number of files may be sent down the line without an end-of-file being sent. An end-of-file is automatically sent on a change of mode to receiving, or may be done explicitly by the directive 'EF:'. 3) In receive mode, non-transparent files (i.e. listing file etc.) are assumed. If a binary file is recieved then TRAN will ignore the current command and request a file name to write the binary file to. 4) A file called 'signof' should be transmitted to close down the link.
C) THE FILE LISTING PROGRAM: FLIST This program can be used to perform the following functions: 1. List the disc file directory a) unordered b) ordered alphabetically 2. Destroy files 3. Rename files 4. Search for the existence of specific files or groups of files COMMANDS When the program expects a command the symbol '>' is output E.g. >A Command Description A : Give an alphabetic listing of the file directory F : Gives an unordered listing of the file directory L : Look for a file or group of files. Fails if not found D : Destroy a file or group of files. Fails if no file or group of files. R : Rename a file. Fails if new file name exists B : List size of a file or group of files. To get a group of files we use the 'wild' character '?' to stand for any other character. If it is the last character input then it is propagated right i.e. 'F?' is expanded to 'F?????' EXAMPLES >L MASK:PRT001 Checks if file PRT001 exists >L MASK:P? Lists all files beginning with P
>L MASK:P?T? Lists all files beinning with P and third letter is an R >D NAME:PRT001 PRT001?:Y If a 'Y' is input then file is destroyed otherwise not. >D NAME:PRT? PRT001?N PRT003?Y Destroys file 'PRT003' but not 'PRT001' or 'PRT004' PRT004?N > >R OLD FILE:TEMP Re-name file 'TEMP' to 'FLIST' NEW FILE:FLIST
D) ARCHIVE PROGRAM .object FILE: ARCHY This program reads and writes files to DECTAPE in a format compatible to the 'local' format used on the ERCC PDP15 and the PHYSICS DEPT. 11/45. .operating PROCEDURE Archive indicates readyness to accept a command by typing:- 'ARCH?' The user should mount a DECTAPE on unit 0 before issuing the first command. The user by typing the appropriate command on the keyboard may:- a) Zero a DECTAPE. b) Print out the directory of a tape. c) Archive a file to DECTAPE d) Restore a file to disc from DECTAPE. e) Delete a file on the DECTAPE f) Stop the program A command consists of:- DIRECTIVE (cr) or DIRECTIVE (space) FILENAMES (cr) A DIRECTIVE consists of the first two letters of the command verb. FILENAMES is one or more file names seperated by commas. COMMAND DESCRIPTION a) ZERO a dectape FORMAT: ZE (cr) This command will delete all the files on a DECTAPE, reclaiming the space. It must be used when a DECTAPE is used for the first time. b) DIRECTORY FORMAT: DI (cr)
This command generates a listing of the DECTAPE directory on the teletype in the form:- FILE NAME xx nnnnnn mmmmmm Where 'xx' is the LENGTH of the file, 'nnnnnn' is the first block the file occupies and 'mmmmmm' is the last block. c) ARCHIVE FORMAT: AR (space) FILENAMES (cr) The file(s) is written out to the DECTAPE 1) If the file does not exist (on the disc), the message 'FILE DOES NOT EXIST' is output. 2) If it is already archived on the DECTAPE the message 'FILE ALREADY ARCHIVED' is output. 3) If the DECTAPE is full, then 'DEC TAPE FULL' is output. d) RESTORE FORMAT: RE (space) FILENAMES (cr) The file(s) is written from the DECTAPE on to the disc (with the same name). 1) If the file exists on the disc, it is overwritten. 2) If the file can't be found on the DECTAPE, the message 'FILE NOT ON ARCHIVE' is output. e) DELETE FORMAT: DE (space) FILENAMES (cr) The file on DECTAPE is destroyed The message 'FILE DOES NOT EXIST' is output if the file can't be found. Note: This command frees the directory entry, but does not reclaim the file space on the tape unless it was the last file to be put on the tape. f) STOP FORMAT: ST (cr) The program terminates
EXTERNAL ROUTINES AVAILABLE UNDER MUSS11 A %SPEC must be given for each routine. 1) %EXTERNALROUTINESPEC WAIT(%INTEGER ticks) This routine suspends the program for the given number of ticks (1 tick = 1/50 sec). If ticks=0 then it is suspended until the operator releases it with 'CO PROG'. 2) %EXTERNALROUTINESPEC NAME(%BYTEINTEGERARRAYNAME KEY) This routine reads in a file name from the currently selected input stream [up to 6 chars - '0'-'9' and 'A'-'Z']. The array should be declared in the form %BYTEINTEGERARRAY KEY (-1:9) [an immediate return is made if KEY(1)=99]. 3) %EXTERNALROUTINESPEC DEFN(%BYTEINTEGERARRAYNAME BUFFER, NAME, %INTEGER STREAM) This routine sets up a STREAM or SQFILE definition. %BYTEINTEGERARRAY BUFFER(0:530) is for the internal use of the stream/SQfile %BYTEINTEGERARRAY NAME (1:6) is a file name (see %ROUTINE NAME) STREAM is the required stream. This routine should be called prior to using a disc file e.g. DEFN(BUFF, KEY, 2) SELECT OUTPUT(2) WRITE(I,5) etc. 4) %EXTERNALROUTINESPEC WRIT(%INTEGER X) This routine writes a positive integer on the current output stream with no leading space.
5) %EXTERNAL %INTEGER %MAP %SPEC COM(%INTEGER ELEMENT NO) Within the supervisor there is a communication area to allow programs to pass information to each other and to control the running of certain 'automatic' programs. The area is 21 words long - designated as 0:24 (octal). The MAP COM allows values to be set into the elements of the area, and be retrieved from it. Although the exact use of each word will be different in each system, the following words are reserved:- word 1: - used for cpu timing (by the program CPU) (octal) 2: - ditto 3: - holds the day (if set by SETIM) 4: - holds the month (ditto) 5: - holds the year (ditto) 21: - used by ACARD, the card reader spooling program. 22: - used by APLOT, the plotter spooling program 23: - used by ALIST, the line printer spooling program 24: - used by A2780, the 2780-emulator spooling program. The MAP may be used in a number of ways, for example:- %INTEGER I I = COM(10); ! read the value of word 10 COM(10) = 2; ! set word 10 to 2 or %INTEGERNAME COMWORD; %INTEGER I COMWORD == COM(10); ! point COMWORD at word 10 I = COMWORD; COMWORD = 2; ! get, then set word 10 6) %EXTERNAL %ROUTINE %SPEC DA(%INTEGER MODE, BLOCK, ADDRESS) This routine is used to read or write blocks to the DISC or DECTAPE. mode = 0 - READ a block from the DISC. = 1 - WRITE a block to the DISC. = 2 - READ a block from DECTAPE. = 3 - WRITE a block to DECTAPE. BLOCK - device block number. ADDRESS - address of 256 word buffer. The routine may also be called with '%INTEGERNAME ADDRESS',
for example:- %INTEGERARRAY A(0:255) DA(0, 500, A(0)) Which will READ block 500 into A. 6) %EXTERNAL %ROUTINE %SPEC FIDENT(%INTEGER TYPE, %C %BYTEINTEGERARRAYNAME KEY) This routine provides information about groups of file names. It is used when it is necessary to automatically allocate file names of a given form, or when groups of file names are being processed. The first four letters of each DISC file are matched against the four letters provided by the caller in KEY(1), KEY(2), KEY(3) and KEY(4). The final two letters of a matching file are then treated as a number, files in the range 0 to 40 are used, the actual use depending on TYPE. TYPE = 0 - returns the name of the first existing file type = 1 - returns the next free file name. The resultant file name is passed back in KEY(1) - KEY(6). An error return (KEY(0)=-1) is made if 1) there is no file (TYPE=0) or 2) no free file name exists (TYPE=1). For example - all files of the type 'PRITXX' can be obtained by a program, one at a time by calling FIDENT(0, A) where A(1) to A(4) are set to 'PRIT'. It should be noted that each file should be 'renamed' or 'destroyed' after use or FIDENT will pick it up again when recalled. The ARRAY should be declared at least (0:6), or if RENAME is going to be called then (-1:6).
7) %EXTERNAL %INTEGER %FN %SPEC RENAME(%BYTEINTEGERARRAYNAME FROM, TO) This function renames the file.'from' to the file 'TO'. The result is zero if the rename succeeds, non-zero if 'FROM' doesn't exist or 'TO' does exist. The ARRAYS should be declared :- %BYTEINTEGERARRAY <name> (-1:6) The first two elements are used by 'RENAME', the file name is in elements one to six. APPENDIX 2 PRELIMINARY USER MANUAL FOR THE SECOND SYSTEM
USER MANUAL FOR DEIMOS B. GILMORE AUGUST 1976
CONTENTS TITLE PAGE System commands. 4 The EDITOR. 7 The IMP compiler. 8 The LINKER. 9 Library manipulation. 11 The debugging program. 12
SYSTEM COMMANDS All commands given to the system are interpreted by the command language interpreter (CLI). The CLI indicates its readiness to accept a command by typing the prompt '>' and '<' overlaid. If a program is running, the CLI can be invoked by typing <escape>, the command prompt should then appear. The input to the CLI has two forms, either:- .a) A FILE NAME, followed by 'stream definitions' or .b) A COMMAND VERB, possibly followed by parameters A) A FILE NAME If a FILE NAME is specified, that file is loaded and the program contained in it is entered. If the file does not exist, or does not contain a program, the message '*NO FRED', where FRED is the name of the file, is output and the command prompt is re-issued. The 'stream definitions' are input in the form:- <input 1>,<input 2>,<input 3>/<output 1>,<output 2>,<output 3> <input 1> etc, each represent a 'stream definition'. A 'stream definition' is of the form:- .TT - which is either input or output from a terminal. .LP - output to a line printer <any other devices on the system, specified in the same way.> <a FILE DEFINITION> A FILE DEFINITION is in the form:- <unit number>.<file name>(<file system number>) The <unit number>, currently, is either '0' or '1' and refers to the physical disc drive. If neither is specified, '0' is assumed. The <file name> consists of an alphanumeric string, which must be preceeded by a letter, of up to 6 characters in length The <file system number> is the file system that the file comes from, or is created in. If none is specified, the users own is used (see the command LOGON) eg FRED - the file called FRED on unit 0 in the users file system. 0.FRED - the same. 1.FRED - The file FRED is taken from disc unit one. FRED(0) - the file FRED from file sys. zero (the systems own one)
1.FRED(25)- the file FRED from disc unit one and file system 25 (octal). .TT - the terminal, input if on the left hand side, output if on the right hand side. The stream definitions are linked into the input and output streams available to an IMP program, for example, if the program .fred is run with the following command:- FRED F1,F2/O1,O2,.TT then input stream one, used by calling 'SELECT INPUT(1)' is mapped to the file 'F1'. A 'SELECT OUTPUT(2)' will send output to the file O2', and 'SELECT OUTPUT(3)' will send the output to the terminal. If a field is left blank, as with <input 3> in the above example, the stream is mapped to 'NULL' - which causes an 'end of file' signal on input and on output, all the output is thrown away. Input stream zero and output stream zero are always mapped to the users terminal. .further EXAMPLES PROG .TT - uses one input stream '.TT', no output stream (apart from zero) is defined. PROG FILE - will read from a file called FILE on stream one. PROG /FILE - no input streams defined (apart from zero), will write to a file called FILE after a 'SELECT OUTPUT(1)'. PROG FILE/FILE - this will read data from a file called FILE and create an output file called file NOTE: When a program does the first 'SELECT OUTPUT(N)', where a file is mapped to that stream, the system will create a temporary file (FILE# in the previous example). When the program stops, or calls 'CLOSE OUTPUT', the original file (FILE) is destroyed and the temporary file (FILE#) RENAMED to that name (FILE). B) A COMMAND VERB There are currently six available system commands, they are:- a) LOGON - used to 'logon' to a file system. b) TASKS - List the running programs on the system. c) HOLD - Stop a task executing. d) FREE - Release a 'HELD' task. e) KILL - Stop a program in a controlled manner. f) PURGE - Immediately remove a task from the system. A) LOGON
This command is called in the form: LOGON nn where 'nn' is a two digit octal number, representing the users file system number. B) TASKS This command has no parameters, it lists out the tasks on the system in the form:- <task name> <task number> <task state> The states of a task are as follows:- STATE MEANING 000001 Task is in the WAIT state. 000002 Task has executed a 'POFF'. 000010 Task is on a CPU QUEUE awaiting execution. 000020 The task is in the 'RUN' state. 000200 The task has been 'HELD'. C) HOLD This command is called in the form: HOLD xxxx where 'xxxx' represents the name of a task running on the system. If the task is currently executing, it is suspended. If the task is waiting for a message, it will be suspended when it next requests the .cpu. D) FREE This command is the converse of HOLD and is called: FREE xxxx it places the task 'xxxx' back on the CPU. E) KILL This command is called in the form: KILL xxxx it has the effect of sending the task called 'xxxx' a message to stop, the task should then stop in a controlled manner tidying up all its streams. F) PURGE This command is called in the form: PURGE xxxx it has an immediate effect, completely removing the task from the system, no attempt is made to tidy the open streams. This command should not normally be used to stop a program, but MUST be used to clear a program from the system that has crashed with an 'ADDRESS .error' or a 'SEG FAULT'.
.note: If a program is still running, HOLD must be called before either KILL or PURGE is used.
THE EDITOR The EDITOR is a PDP11 version of the COMPATIBLE CONTEXT .editor. For general information on the Editor, see the USER GUIDE of the COMPATIBLE CONTEXT EDITOR by H Dewar. The command for calling the Editor has three possible forms as illustrated below: E /TEST - to produce a new file called TEST. E TEST - to edit an existing file called TEST E TEST/TEST2 - to produce a new file called TEST2 from an existing file called TEST. .notes 1) The Editor prompts '>' when it is ready to accept a command and ':' when it expects a line of input (COMMAND: GET). 2) This version of the Editor uses a 'window' of the file, this will not normally be apparent, but it does mean that the command 'M-*' will not necessarily return right to the top of the file.
RUNNING THE IMP COMPILER The IMP compiler is a three pass compiler to which a fourth pass, a LINKING phase, is automatically called for %BEGIN .. %ENDOFPROGRAM programs There are four main ways of calling it:- .imp A/B - which compiles source file 'A' to object 'B' .imp A/,L - which only does one pass and creates a listing file 'L' (note: 'L' can be either a filename, '.TT' or '.LP'). .imp A/B,L - which creates both an object file and a listing file. .imp A,.TT/B - this form is used to change the LINKER defaults, for more details of the defaults, see the section on the LINKER. .notes 1) At present, the program 'IMPX' must be run to avoid the linking phase for %EXTERNALROUTINE files. In this case, the file 'B' above is the compilers third pass output. 2) The test compiler is accessed by running the program 'NIMP'. 3) The first pass automatically uses a file of '%SPECS' called 'PRIMS' which is taken from the system file system. 4) The first pass creates a temporary output file 'O' for use with the econd pass. The second pass creates 'O2' and 'O3' and the third pass 'OY'. 5) The output from the third pass 'OY' is useful. It can be used as input to the programs 'RECODE' and 'VIEW' if it is necessary to de-compile the compiler output. If the linker is to be run as a seperate 4th pass, the file 'OY' is used as its input.
THE LINKER The LINKER is normally run automatically as a fourth pass to the IMP compiler. It is run individually by typing one of the two following forms of command to the COMMAND LANGUAGE INTERPRETER. LINK A/B or LINK A,.TT/B Both of the above commands take the file 'A', which must be the output from the third pass of the compiler and create a runnable file .'b'. The second form of the command overrides the standard LINKER defaults, the LINKER prompts for the new data as follows (defaults in brackets):- NAME: - up to 4 characters are typed in as the TASK NAME for the program (the first four characters of the object file name are used). STACK: - the desired stack size (in octal bytes), excluding the GLA (default: 14000). STREAMS: - the max number of input and output streams that the program is going to use, excluding INPUT and OUTPUT (0) (default: 3). If a program has external references in it, the LINKER will first attempt to satisfy then using 'LIB000' in the users file system. If there are still unsatisfied references, the LINKER will look at 'LIB000' in file system zero (the system file system). For more information on LIBRARIES, see the section on them. A sample LINKER output map is given below:- CODE: 040000 GLA: 140020 XREF:PON POFF PONOFF MAPVIRT XDEF: 040000 #GO FILE:SHARED CODE: 046506 GLA: 140752 XREF: 004000 RUN XDEF: 022656 PON XDEF: 022700 POFF XDEF: 022736 MAPVIRT XDEF: 023006 MAPABS TOTALS: CODE = 006506 GLA/STACK = 002016 The TASK NAME of the program (DBUG) is printed along with the base address for its code (040000) and its GLA (140020). The .'xref' refers to 'external references' from that section of code (in this case they are all declared by the system). The 'XDEF' is an 'external definition', in this case '#GO' which is the entry point for the main program.
The 'FILE:' indicates that the LINKER has loaded an object file , it specifies its name (SHARED) and the start address of its code (046506) and GLA (140752) sections. The list beneath that is the 'external definitions', in this case entry points that the file contains. The last line gives the overall code length of the program (006506) and the total size of the GLA and the declared stack. If any references are left undeclared, the LINKER will list them along with an 'UNDEFINED REFERENCE' message. If the LINKER attempts to load a file that contains an entry point that has already been loaded, the message '*DOUBLE DEF' is output and the LINKER stops.
LIBRARY MANIPULATION When the LINKER finds an EXTERNAL REFERENCE in a program file it will attempt to satisfy the reference by:- 1) Searching the library 'LIB000' in the USER file system, loading object files as necessary, then 2) Searching the library 'LIB000' in the SYSTEM file system (zero). There are three programs currently available to the user to manipulate libraries, they are:- 1) NEWLIB - creates a new library file. 2) INSERT - Inserts the entries of an object file into a library. 3) INDEX - lists the contents of a library. NOTE: Each of the programs will manipulate libraries other than 'LIB000', but at present the LINKER will not link them. 1) NEWLIB The command for using NEWLIB is as follows:- NEWLIB /LIB This command will create a new library file 'LIB', if it already exists the old copy is destroyrd. 2) INSERT There are two main forms of this command as follows: INSERT TESTY,LIB/LIB and INSERT TESTY,LIB/LIB2 The first command will add the entries of the file called TESTY into the library called LIB. The second command will add the contents of the file called TESTY into the library called LIB, creating a new library called LIB2. 3) INDEX The form of this command is as follows:- INDEX LIB This command will print out all the entries in the library file 'LIB'
DEBUGGING PROGRAM OBJECT: DBUG This program is used as an aid to debugging programs, it will mormally be 'linked' to a running program on the system using the command 'T' (for details see later), all accesses to locations will then be made in that programs virtual memory. It may be used to:- 1) SET and CLEAR breakpoints 2) Dump out the PSECT, REGISTERS and/or the IMP STACK. 3) EXAMINE and CHANGE locations in core. 4) DUMP general areas of core. DEBUG indicates its readiness to accept commands by typing 'DEBUG:'. The following commands may be used. T - Set Task number of program to be debugged. B - Set breakpoint. C - Clear breakpoint. N - Set a new program code base. R - Dump the REGISTERS. P - Dump the PSECT. I - Dump the IMP stack. A - Do 'P', 'R', and 'I'. D - Dump an area of core. O - Change the output device. W - WAIT DEBUG. S - Stop DEBUG. ? - Print options. In addition to these commands, there is an implied command, activated by typing an octal digit, that enters the location examination/change part of DEBUG. A detailed description of each command follows. T - SET TASK NUMBER The prompt 'TASK ID:' is output and the (octal) ID of the program to be debugged should be entered. The TASK ID of a running program may be obtained by typing the command 'TASKS' to the command language interpreter. NOTE: Only the commands 'T', 'N', 'O', 'S' and 'W' may be used before 'T' is used for the first time.
B - SET BREAKPOINT The prompt 'ADDR:' is output, the reply is the RELATIVE address (wrt the start of the program) of the desired breakpoint. Debug will remember the contents and place a 'BR ' in the location. This will cause the program to loop when it executes that instruction. Debug replies: BP: n ADDR: n2 CONT= n3 - where 'n' is the breakpoint number (between 0 and 20), 'n2' is the virtual address, and 'n3' the original contents. The message 'BP TABLE FULL' is output if more than 21 breakpoints are used. See the command 'N' for setting breakpoints in external routines. C - CLEAR BREAKPOINTS Prompts 'NO?'. The breakpoint number should be typed. 'A' or '-1' is typed if ALL the breakpoints are to be cleared. If the specific breakpoint has not been set, the message '?' is output. The original contents are replaced. N - SET A NEW PROGRAM CODE BASE Prompts 'NEW PROGRAM CODE:'. Reply giving the new address. This command is useful for programs using external routines. To set a breakpoint in an external routine, the code base is set to that of the external routine, as printed out by the LINKER, and the relative address specified. This does not effect any previously set breakpoints. R - PRINT REGISTERS. This command prints the registers of the nominated task. The LOCAL NAME BASE (LNB) for the outer level is also printed.
P - PRINT THE PSECT The PSECT (own system variables) of the nominated task is printed. The command :- 1) Prints the name of the task 2) Prints the state of the task. 3) Indicates whether there are messages queued. 4) Calls 'REGISTERS' to dump the registers out. 5) Prints the contents of the segmentation registers in the form:- <REGISTER NUMBER> <ADDRESS> <LENGTH> <ACCESS> I - PRINT THE IMP STACK The entire IMP STACK is printed on the output device. NOTE: The GLA of the program is held at the low address end of the stack, the IMP stack (ie the SP stack) starts at the high address end and works towards the low address end. is not the same as the start of the stack. A - PRINT ALL The command executes a print psect (P), print registers (R) and the IMP stack (I). This command is useful for dumping all the relevant information about a program onto the line printer (see command 'O'). D - DUMP AN AREA OF CORE Prompts 'FROM:' and 'LENGTH:'. Both numbers should be typed in octal and the area of core from 'FROM' to 'FROM+LENGTH' is output. NOTE: 1) On all the dumps 'ZEROES' is ouput if one or more entire line contains zero. 2) An ISO equivalent is printed on the RHS of the dump. O - CHANGE THE OUTPUT DEVICE Prompts 'STREAM:'. The reply is used in the form 'SELECT OUTPUT(N)' for the output of commands R,P,I,A and D. By calling 'DBUG' in the form:-
DBUG /L or DBUG /.LP etc the output may be directed to the file 'L' or to the line printer. W - WAIT DEBUG This command is used to suspend DEBUG if it is necessary to input to a program on the same teletype. It is restarted by (ESCAPE) FREE DBUG S - STOP DEBUG Debug halts. Note: all breakpoints are cleared. IMPLIED COMMAND TO EXAMINE/CHANGE CORE ADDRESSES This command accepts the following instructions:- Note 'N' and 'M' represent numbers input in octal. N : prints contents of N. N+C : prints contents of (N+ program base). N+I : prints contents of (N+ IMP STK base). N+RM : prints contents of (N+REGISTER M) N(+ options)=m : puts M into N eg: DEBUG:100 (cr) - will print contents of locn 100. DEBUG:100+R5 (cr) - will print contents of 100 on from reg. 5. DEBUG:100+R5=200 (cr) - ditto, except plants 200. NOTES An '*N' at the end of the command will cause the following 'N' locations to be dumped out ('N' may be negative). '+' or '+=M' may be entered as a new command, this takes the last location used and steps it up by 2 (-2 if '-' is used).
APPENDIX 3 LISTING OF THE KERNEL OF THE SECOND SYSTEM CONTROL K'100001'; ! 'SYSTEM' ROUTINE ENTRY+MUL+TRUSTED PERMROUTINESPEC SVC PERMINTEGERMAPSPEC INTEGER(INTEGER X); ! USED IN INIT RECORDFORMAT DUMMY(INTEGER X) CONSTRECORD (DUMMY) NAME NULL=0 BEGIN CONSTINTEGER TASK LOW LIMIT=30 CONSTINTEGER TASK LIMIT=50 CONSTINTEGER FREE CELLS=50 CONSTINTEGER NO OF SERVICES=50 CONSTINTEGER NO OF INTS=10 CONSTINTEGER FRAG NO=30 CONSTINTEGER PSECT LENGTH=47 CONSTINTEGER SVC LIMIT=16 CONSTINTEGER INT LIMIT=-7 CONSTINTEGER K SEG LIMIT=50 CONSTINTEGER TTID=30; ! TASK LO LIMIT CONSTINTEGER DKID=31; ! " " " +1 CONSTINTEGER DIRID=32; ! " " " +2 CONSTINTEGER LOADID=33; ! " " " +2 CONSTINTEGER MOTHER=34; ! " " " +3 CONSTINTEGERNAME PS=K'177776'; ! STATUS WORD CONSTINTEGERNAME STACK LIMIT=K'177774' RECORDFORMAT EF(RECORD (EF) NAME LINK, INTEGER ID, A1) RECORDFORMAT QF(RECORD (EF) NAME E) RECORDFORMAT TF(RECORD (TF) NAME LINK, INTEGER ID, T) RECORDFORMAT KSEGF(INTEGER USE, DADD, PAR, PDR) RECORDFORMAT KSEGLF(RECORD (KSEGLF) NAME L, INTEGER B, C, D) RECORDFORMAT UREGSF(INTEGER R0, R1, R2, R3, R4, R5, PC, C PS, SP) RECORDFORMAT SEGF(INTEGER PAR, PDR, RECORD (KSEGF) NAME KSL, C INTEGER USE) RECORDFORMAT PSECTF(BYTEINTEGER ID, STATE, C BYTEINTEGERARRAY NAME(0:3), C BYTEINTEGER PRIO, RECORD (QF) POFFQ, C RECORD (UREGSF) URS, INTEGER TRAPV, C RECORD (SEGF) ARRAY SEG(0:7)) RECORDFORMAT PSTF(RECORD (PSECTF) NAME P) RECORDFORMAT PF(BYTEINTEGER SERVICE, REPLY, C INTEGER A1, A2, A3) RECORDFORMAT P2F(INTEGER D, A1, A2, A3)
RECORDFORMAT MAINPF(RECORD (MAINPF) NAME L, RECORD (P2F) P) RECORDFORMAT STOREF(INTEGER LEN, BLOCK NO) RECORDFORMAT ADDRFN(RECORD (ADDRFN) NAME PSECTA, LAST32, COREA) CONSTRECORD (ADDRFN) NAME ADDS=K'120' RECORDFORMAT D1F(INTEGER X) RECORDFORMAT D2F(RECORD (QF) NAME X) RECORD (EF) NAME E RECORD (TF) NAME T, T2, TN, TB RECORD (PSECTF) NAME PSECT, PSECT2, PSECTN, PSECT3 RECORD (SEGF) NAME SEG1, SEG2 RECORD (KSEGF) NAME KS1, KS2 RECORD (KSEGLF) NAME KL RECORD (KSEGLF) NAME FREE SEGL RECORD (QF) ARRAY CPUQ(0:7) !* RECORD (PF) PX RECORD (PF) NAME P, Q RECORD (P2F) NAME P2, Q2 RECORD (MAINPF) NAME MAINP, MP2 RECORD (QF) NAME FREE PARAM RECORD (QF) TIME Q; ! HEAD OF TIMER LIST INTEGER QU, SERVICE, TICKS, LEN, I, PT, L2, BLOCK, S, ID RECORD (D1F) NAME D1 RECORD (D2F) D2 RECORD (PSTF) ARRAY PSECTA(TASK LOW LIMIT:TASK LIMIT) RECORD (EF) ARRAY ONQ(TASK LOW LIMIT:TASK LIMIT) RECORD (TF) ARRAY ONTMQ(TASK LOW LIMIT:TASK LIMIT) RECORD (MAINPF) ARRAY PARAMS(0:FREE CELLS) RECORD (STOREF) ARRAY STORE(0:FRAG NO) RECORD (STOREF) NAME ST1 RECORD (KSEGLF) ARRAY KSEGL(1:K SEG LIMIT) RECORD (P2F) ARRAY LAST THIRTY2(0:31); OWNINTEGER LAST=0 OWNBYTEINTEGERARRAY SER MAP(INT LIMIT:NO OF SERVICES)= C 0, 0, 0, MOTHER, DKID, TTID, TTID, 0, TTID, 0, DKID, DIRID, LOADID, 0, MOTHER, 0(43) CONSTINTEGER FAULT SER=-4
!! TU 16 INT = -5 !! DQS11 TX INT = -6 !! DQS11 RX INT = -7 EXTERNALINTEGERFNSPEC RUN(RECORD (PSECTF) NAME PSECT) ROUTINESPEC INITIALISE ROUTINESPEC FILL SEG(RECORD (SEGF) NAME SEG, C RECORD (KSEGF) NAME KS, INTEGER PAR, PDR) !* ROUTINESPEC PUSH(RECORD (QF) NAME Q, RECORD (EF) NAME E) RECORD (EF) MAPSPEC POP(RECORD (QF) NAME Q) ROUTINESPEC SCHEDULE ROUTINESPEC DEALLOCATE(RECORD (KSEGF) NAME KS) ROUTINESPEC FAULT(INTEGER I) !*********************************************** !* SUPERVISOR STATES * !*********************************************** CONSTINTEGER IDLE ST=-1 CONSTINTEGER TASK ST=0 !********************************************** !* TASK STATES * !********************************************** CONSTINTEGER T WAIT=1 CONSTINTEGER T POFF=2 CONSTINTEGER T TIME=4 CONSTBYTEINTEGER T CPUQ=8 CONSTBYTEINTEGER T RUN=16 CONSTBYTEINTEGER T SUSP=K'200' !*********************************************** !* SVC SERVICES (BY EMT VALUE) * !*********************************************** CONSTINTEGER INTERRUPT=-1 CONSTINTEGER WAIT=1 CONSTINTEGER PON R=2 CONSTINTEGER POFF R=3 CONSTINTEGER INSERT=4 CONSTINTEGER DELETE=5 CONSTINTEGER ALLOCATE CORE=6 CONSTINTEGER FREESP=7 CONSTINTEGER SET TIME=8 CONSTINTEGER SCHEDULE T=9 CONSTINTEGER MAP VIRT=10 CONSTINTEGER GET ABS=11 CONSTINTEGER GET ID=12 CONSTINTEGER LINKIN=13 CONSTINTEGER MAP SHARED=14 CONSTINTEGER MAP HREGS=15
CONSTINTEGER MAP PSECT=16 !************************************************ !* STATIC CORE LOCATIONS * !************************************************ CONSTINTEGERNAME INT VALUE=K'40' CONSTINTEGERNAME SUPER =K'42' CONSTINTEGERNAME ALARM F=K'44' CONSTINTEGERNAME S ENTRY=K'46' CONSTINTEGERNAME PSECT AREA=K'50' CONSTINTEGERNAME FAULT TYPE=K'52' !************************************************* SWITCH SER(-1:SVC LIMIT) OWNINTEGERARRAY PRESET(0:234)= C 0,M'TT',M' ',4,0,0(6),K'20210',K'140200',K'120200',0,0(32), 0,M'KD',M' ',4,0,0(6),K'20210',K'140200',K'120200',0,0(32), 0,M'ID',M'TR',3,0,0(6),K'20210',K'140140',K'120200',0,0(32), 0,M'OL',M'DA',1,0,0(6),K'20032',K'140040',K'120300',0,0(32), 0,M'OM',M'HT',3,0,0(6),K'20032',K'140040',K'120200',0,0(32) !*************************************************** !* START OF CODE PROPER * !*************************************************** INITIALISE; ! HELD IN DE-ALLOCATABLE SPACE !***************************************************** !* BASIC LOOP IS CPU SCHEDULER * !***************************************************** CYCLE E==NULL CYCLE QU = 7, -1, 0 IF NOT CPUQ(QU)_E==NULL START E==POP(CPUQ(QU)) EXIT FINISH REPEAT IF E==NULL START; ! IDLE SUPER=IDLE ST; ! MARK SUPERVISOR IN IDLE PS=0; ! SET PRIO=ZERO IDLE LP: *1; ! EXECUTE 'WAIT' ->IDLE LP FINISH !* FOUND PROCESS, SO SCHEDULE PSECT==PSECTA(E_ID)_P; ! MAP 'PSECT' TO ACTUAL SPACE GO: IF PSECT_STATE&T SUSP#0 THENCONTINUE; ! DON'T RUN IT SUPER=TASK ST; ! GOING INTO 'USER' PROCESS PSECT_STATE=T RUN SERVICE=RUN(PSECT); ! EXTERNAL
->SER(SERVICE) IF SERVICE<=SVC LIMIT FAULT TYPE=5 ERROR: INT VALUE=FAULT SER SER(INTERRUPT): ; ! DEVICE INTERRUPT IF INT VALUE#FAULT SER START SCHEDULE UNLESS SUPER=IDLE ST ELSE PX_A2=PSECT_ID PX_A3=FAULT TYPE FINISH ->CLOCKINT IF INT VALUE=0 ID=SER MAP(INT VALUE) PX_SERVICE=INT VALUE PX_REPLY=0; ! INTERRUPT PX_A1=INT VALUE; ! REMOVE IN DUE COURSE P2==PX; P==P2 !* AND SEND IT !! SEND MESS TO RELEVANT TASK ->DO PON SER(WAIT): PSECT_STATE=T WAIT CONTINUE; ! FIND SOMETHING ELSE SER(PON R): SCHEDULE P2==PSECT_URS; ! MAP PARAM AREA TO HIS REGS P==P2 !* NOW PLANT ON Q !* AND SCHEDULE PROCESS IF NECESSARY S=P_SERVICE; ! PICK UP THE ROUTING ID=SER MAP(S); ! AND FIND THE OWNING PROCESS DO PON: PSECT3==PSECTA(ID)_P; ! PSECT OF RECEIVING MESSAGE FAULT TYPE=6 AND ->ERROR IF PSECT3==NULL OR ID=0 PSECT==PSECT3 Q==PSECT_URS; Q2==Q IF PSECT_STATE&T POFF#0 START; ! WAITING FOR POFF IF Q_SERVICE=0 OR Q2_D=P2_D START PON EXECUTE: Q2 == PSECT_URS Q2 = P2 LAST THIRTY2(LAST)=P2; LAST=(LAST+1)&31 SCHEDULE CONTINUE FINISH FINISH MAINP==FREE PARAM; ! PICK UP NEW PARAM CELL FREE PARAM==MAINP_L; ! RELINK FREE LIST MAINP_P = P2 PUSH(PSECT_POFFQ, MAINP); ! PUT ON TASK POFF Q CONTINUE
SER(POFF R):; ! USER POFF UNLESS PSECT_POFFQ_E==NULL START; ! Q NON ZERO MP2==PSECT_POFFQ_E; ! GET LAST ENTRY Q==PSECT_URS; Q2==Q UNTIL MP2==MAINP CYCLE; ! CYCLE WHOLE Q MAINP==POP(PSECT_POFFQ) P==MAINP_P; P2==P IF Q_SERVICE=0 OR Q2_D=P2_D START MAINP_L==FREE PARAM; FREE PARAM==MAINP; ! RELINK ON Q ->PON EXECUTE FINISH PUSH(PSECT_POFFQ, MAINP) REPEAT FINISH PSECT_STATE=T POFF CONTINUE SER(SCHEDULE T): ! R0 IS ID OF TASK TO BE SCHEDULED SCHEDULE; ! RE-SCHEDULE CALLER PSECT==PSECTA(PSECT_URS_R0)_P FAULT(7) IF PSECT==NULL SCHEDULE CONTINUE SER(DELETE): ! DELETE THE RUNNING TASK IF PSECT_ID=LOADID START SCHEDULE; ! RE-SCHEDULE LOADER PSECT==PSECTA(PSECT_URS_R0)_P FINISH CYCLE; ! CLEAR OUT THE POFF Q MAINP==POP(PSECT_POFFQ) EXITIF MAINP==NULL MAINP_L==FREE PARAM; FREE PARAM==MAINP REPEAT CYCLE I=7, -1, 0; ! GO DOWN THE SEGS KS1==PSECT_SEG(I)_KSL UNLESS KS1 == NULL START KS1_USE=KS1_USE-1 DEALLOCATE(KS1) IF KS1_USE=0 FINISH REPEAT PSECTA(PSECT_ID)_P==NULL REPEAT; ! OF MAIN LOOP CLOCKINT: ! CLOCK HAS OVERFLOWED !* SEND MESSAGE TO FIRST TASK ON Q !* SET CLOCK TO NEXT TIME TN==POP(TIME Q) UNLESS TIMEQ_E==NULL THEN ALARM F=TIMEQ_E_A1 ID=TN_ID PX_SERVICE=ID; PX_REPLY=0
P2==PX; TN_T=0 ->DO PON SER(SET TIME): ! SET TIMER FOR URS_R0 TICKS ID=PSECT_ID IF ONTMQ(ID)_T#0 THEN FAULT(6); ! ON Q ALREADY TN==ONTMQ(ID) TICKS=PSECT_URS_R0; ! NO OF TICKS TB==TIMEQ_E; ! LAST ENTRY ->BOT IF TB==NULL IF TB_LINK==TB THEN T==TB ELSE T==TB_LINK T_T=ALARM F; ! ADJUST FOR TIME PAST T2==TB CYCLE; ! CHECK THE LIST IF TICKS<T_T START; ! PUT ON Q HERE TN_LINK==T2_LINK; T2_LINK==TN T_T=T_T-TICKS EXIT FINISH TICKS=TICKS-T_T IF T==TB START; ! AT BOTTOM BOT: PUSH(TIMEQ, TN); ! PLANT ON END EXIT FINISH T2==T T==T2_LINK REPEAT TN_T=TICKS ALARM F = TICKS; ! START THE CLOCK ->GO; ! IMMEDIATE RESCHEDULE SER(ALLOCATE CORE): PT= -1 IF PSECT_ID <= LOADID START LEN=PSECT_URS_R0; ! CORE REQUIRED IN BLOCKS PSECT_URS_R0=0; ! URS_R1 IS THE NEW SEG PT=-1; L2=0 CYCLE I=FRAG NO, -1, 0 IF STORE(I)_LEN>LEN AND STORE(I)_LEN>L2 THEN C PT=I AND L2=STORE(I)_LEN REPEAT FINISH IF PT=-1 THEN ->GO; ! NO CORE ST1==STORE(PT) BLOCK=ST1_BLOCK NO; ! ADDRESS OF BLOCK (IN BLOCKS) IF L2>LEN START; ! EXCESS, SO TRIM ST1_BLOCKNO=ST1_BLOCK NO+LEN ST1_LEN=ST1_LEN-LEN ELSE E=0 KL==FREE SEGL FAULT(12) IF KL==NULL; ! NO FREE SEGMENT CELLS FREE SEGL==KL_L KS1==KL; ! MAP THE 'REAL' TYPE ON KS1_USE=0; ! 'SHARED' WILL MAKE IT '1'
KS1_PAR=BLOCK; KS1_PDR=(LEN-1)<<8!6 SEG1==PSECTN_SEG(PSECT_URS_R1) PSECT_URS_R0=BLOCK ->DO SHARED; ! FILL HIS SEG ENTRY SER(MAP VIRT): ! MAP USER A TO B ! R0 = TARGET ID ! R1 = TARGET SEG ! R2 = CALLERS SEG ! R1 = -1 SIGNIFIES DROP SEG S=0 IF PSECT_ID=LOADID THEN S=6 SEG1==PSECT_SEG(PSECT_URS_R2); ! GET CALLERS SEG IF PSECT_URS_R1<0 START; ! DROP SEGMENT KS1==SEG1_KSL IF KS1==NULL THEN FAULT(10); ! NO SEG KS1_USE=KS1_USE-1 IF KS1_USE=0 THEN DEALLOCATE(KS1) SEG1=0; ! ZERO CALLERS ENTRY ELSE !! MAP TO DESIRED SEG PSECT2==PSECTA(PSECT_URS_R0)_P FAULT(4) IF PSECT2==NULL KS1==PSECT2_SEG(PSECT_URS_R1)_KSL DO SHARED: FAULT(13) IF KS1==NULL SEG1_PAR=KS1_PAR; SEG1_PDR=KS1_PDR!S SEG1_KSL==KS1 KS1_USE=KS1_USE+1 FINISH ->GO SER(GET ABS): ! GET ABSOLUTE ADDR OF VIRT SEG ! R0 = TARGET ID ! R1 = TARGET SEG ! R2 = 0 (DROP SEG) = 1 (GET SEG) PSECT2==PSECTA(PSECT_URS_R0)_P FAULT(5) IF PSECT2==NULL SEG1==PSECT2_SEG(PSECT_URS_R1) KS1==SEG1_KSL IF PSECT_URS_R2#0 START PSECT_URS_R0=SEG1_PAR PSECT_URS_R1=SEG1_PDR KS1_USE=KS1_USE+1 ELSE KS1_USE=KS1_USE-1 IF KS1_USE=0 THEN DEALLOCATE(KS1) FINISH ->GO SER(GET ID): ! RETURN ID OF TASK IN R0 PSECT_URS_R0=PSECT_ID ->GO
SER(LINKIN): ! R0 IS REQUIRED SERVICE SER MAP(PSECT_URS_R0)=PSECT_ID ->GO SER(MAP SHARED): ! R0 IS ID, R1=SEG, R2=SHARED NO PSECT2==PSECTA(PSECT_URS_R0)_P FAULT(8) IF PSECT2==NULL SEG1==PSECT2_SEG(PSECT_URS_R1) KS1==PSECT_SEG(1)_KSL; S=2 ->DO SHARED SER(INSERT): ! ALLOCATE A NEW PSECT (AND MAP TO R0?) CYCLE ID=TASK LOW LIMIT, 1, TASK LIMIT EXIT IF PSECTA(ID)_P==NULL REPEAT D1==D2; ! DUMMY FORMATS TO STUFF ADDRESS D1_X=PSECT AREA+(ID-MOTHER-1)<<7 !! SHOULD BE *(PSECT LENGTH*2) PSECTA(ID)_P==D2_X PSECT2==D2_X; ! MAP TO ARRAY AND PSECT2 PSECT2_ID=ID SEG1==PSECT_SEG(PSECT_URS_R0); ! MAP TO LOADER PSECT SEG1_PAR=D1_X>>6; SEG1_PDR=1<<8!6; ! 2 SEGS, READ/WRITE SER MAP(ID)=ID; ! MAP HIS MAIN SERVICE IN PSECTN==PSECT2; ! FOR USE WITH GET CORE ->GO; ! RESTART LOADER SER(MAP HREGS): ! MAP HARDWARE REGS TO SEG R0 SEG1==PSECT_SEG(PSECT_URS_R0) SEG1_PAR=K'7600'; SEG1_PDR=K'77406'; SEG1_KSL==NULL ->GO SER(MAP PSECT): ! MAP PSECT 'R0' TO SEG IN R1 I=PSECT_URS_R1 ID=PSECT_URS_R0 SEG1==PSECT_SEG(I); SEG1=0 PT=0 IF PSECT_ID=LOADID THEN S=2<<8!6 ELSE S=2<<8!2 D2_X==PSECTA(ID)_P UNLESS D2_X==NULL START SEG1_PAR=D1_X>>6; ! MAP TO THE START OF ITS BLOCK SEG1_PDR=S; ! ACCESS DEPENDS ON TASK PT=I<<13!(D1_X&K'77'); ! POINT R0 TO ITS BEGINNING FINISH PSECT_URS_R0=PT ->GO ROUTINE PUSH(RECORD (QF) NAME Q, RECORD (EF) NAME E) IF Q_E==NULL THEN E_LINK==E ELSESTART E_LINK==Q_E_LINK Q_E_LINK==E
FINISH Q_E==E END RECORD (EF) MAP POP (RECORD (QF) NAME Q) RECORD (EF) NAME E IF Q_E==NULL THEN RESULT==NULL E==Q_E_LINK IF NOT E==Q_E START; ! ONE ITEM ONLY Q_E_LINK==E_LINK ELSE E==Q_E Q_E==NULL FINISH RESULT == E END ROUTINE SCHEDULE PSECT_STATE=(PSECT_STATE&T SUSP)!T CPUQ PUSH(CPUQ(PSECT_PRIO), ONQ(PSECT_ID)) END ROUTINE DEALLOCATE(RECORD (KSEGF) NAME KS) RECORD (STOREF) NAME S, S2, S3 RECORD (KSEGLF) NAME KSL INTEGER I, BOT, BLOCK, LEN BLOCK=KS_PAR; LEN=KS_PDR>>8+1 BOT=BLOCK+LEN; S2==NULL CYCLE I=FRAG NO, -1, 0 S==STORE(I) IF S_BLOCK NO+S_LEN=BLOCK START IF S2==NULL START S_LEN=S_LEN+LEN; ! ADD IT ON THE BOTTOM S2==S; ! REMEMBER IT ELSE S_LEN=S_LEN+S2_LEN S2_BLOCK NO=0; S2_LEN=0 EXIT FINISH ELSE IF S_BLOCK NO=BOT START IF S2==NULL START; ! NOT FOUND THE UPPER HALF S_BLOCK NO=BLOCK; S_LEN=S_LEN+LEN S2==S; ! MARK FOUND ELSE S_BLOCK NO=S2_BLOCK NO S_LEN=S_LEN+S2_LEN S2_BLOCK NO=0; S2_LEN=0 EXIT FINISH FINISH FINISH IF S_BLOCK NO=0 THEN S3==S; ! REMEMBER EMPTY SLOT
REPEAT IF S2==NULL START S3_BLOCK NO=BLOCK; S3_LEN=LEN FINISH KSL==KS KSL_L==FREE SEGL FREE SEGL==KSL; ! MAP SEG ENTRY BACK TO FREE LIST END ROUTINE FAULT(INTEGER I) *K'016500'; *2; ! MOV 2(LNB),R0 *0 END ROUTINE INITIALISE RECORDFORMAT SF(INTEGERARRAY SEG(0:7)) CONSTRECORD (SF) NAME K PAR=K'172340' CONSTRECORD (SF) NAME K PDR=K'172300' CONSTRECORD (SF) NAME U PAR=K'177640' CONSTRECORD (SF) NAME U PDR=K'177600' CONSTINTEGERNAME SR0=K'177572' CONSTINTEGERNAME SR2=K'177576' CONSTINTEGERNAME CLOCK V=K'177546' RECORDFORMAT DEDLOC F(INTEGERARRAY D(0:4)) CONSTRECORD (DEDLOCF) NAME DEDLOC=K'60000' INTEGER I, PT, BASE, TOP CORE, ID, TOP, PERM, PERML, STK, TC INTEGER KST, STKL RECORDFORMAT D1F(INTEGERNAME X) RECORDFORMAT D2F(RECORD (QF) NAME X) RECORD (D1F) NAME D1 RECORD (D2F) D2 K PAR=0; K PDR=0 CYCLE I=0, 1, 6 K PAR_SEG(I)=I<<7; K PDR_SEG(I)=K'77406' REPEAT K PAR_SEG(7)=K'7600'; ! MAP TO HARDWARE VECTORS K PDR_SEG(7)=K'77406' UPAR=0; UPDR=0 SR0=1; ! GET IT GOING PS=K'340'; ! ENSUE UNINTERRUPTABLE CLOCKV=K'100' !! STACK LIMIT=K'400' D1==D2 KST=2 CPUQ(I)=0 FOR I=0, 1, 7
LAST THIRTY2(I)=0 FOR I=0,1,31 SUPER=IDLE ST ALARM F=0 FOR I=TASK LOW LIMIT, 1, TASK LIMIT CYCLE PSECTA(I)_P==NULL ONQ(I)=0; ONQ(I)_ID=I ONTMQ(I)=0; ONTMQ(I)_ID=I REPEAT ID=TASK LOW LIMIT PERM=DEDLOC_D(3)>>6; ! PICKUP ADDR OF PERM TOP=DEDLOC_D(5)>>6 PERML=((TOP-PERM-1)<<8)&K'177400'!2; ! READ ONLY TOP CORE=DEDLOC_D(0); TC=TOP CORE CYCLE I=TOP CORE, 2, K'137336' IF I=K'60000' THEN I=K'60060' INTEGER(I)=0 REPEAT PSECT AREA=TOP CORE TOP CORE=TOP CORE+K'200'*10; ! ONLY 10 TASKS????? I=5 CYCLE EXITIF DEDLOC_D(I)=TC D1_X==PRESET(PT) PSECTA(ID)_P==D2_X PSECT==D2_X PSECT_ID=ID PT=PT+PSECT LENGTH BASE=DEDLOC_D(I)>>6 STK=DEDLOC_D(I+1)>>6 TOP=DEDLOC_D(I+2)>>6 FILL SEG(PSECT_SEG(2), KSEGL(KST), BASE, (STK-BASE-1)<<8!6) KST = KST+1; ! FILL IN CODE ADDRESS FILL SEG(PSECT_SEG(6), KSEGL(KST), STK, (TOP-STK-1)<<8!6) KST = KST+1; ! FILL IN STACK AREA PSECT_SEG(7)_PAR=K'7600' PSECT_SEG(7)_PDR=K'77406' SER MAP(ID)=ID PSECT_SEG(1)_PAR=PERM; PSECT_SEG(1)_PDR=PERML PSECT_SEG(1)_KSL==KSEGL(1) PSECT_URS_R1=K'140000'; ! VIRT ADD OF TOP OF STK PSECT_URS_SP=K'140000'+(TOP-STK)<<6 IF ID>=LOADID START FILL SEG(PSECT_SEG(7), KSEGL(KST), C TOP CORE>>6, K'13'<<8!6); ! FILL IN I/O SEG TOP CORE=TOP CORE+K'1400'; KST=KST+1 PSECT_URS_R2=2; ! INDICATE LOADER TO PERM INTEGER(STK<<6+4)=X'0A41'; ! A,NL PSECT_URS_R0=K'140004'; ! POINTS TO ABOVE FINISH SCHEDULE I=I+2; ID=ID+1 REPEAT I=TOP CORE>>6 STORE(0)_BLOCK NO=I
STORE(0)_LEN=K'2000'-I ADDS_PSECTA==PSECTA(TASK LOW LIMIT) ADDS_LAST32==LAST THIRTY2(0) ADDS_COREA==STORE(0) PARAMS(I)_L==PARAMS(I+1) FOR I=0, 1, FREE CELLS-1 FREE PARAM==PARAMS(0) CYCLE I=KST, 1, K SEG LIMIT-1 KSEGL(I)=0 KSEGL(I)_L==KSEGL(I+1) REPEAT FREE SEGL==KSEGL(KST) KS1==KSEGL(1) KS1_PAR=PERM; KS1_PDR=PERML KS1_USE = 10 K PDR_SEG(I)=0 FOR I=3, 1, 6 END ROUTINE FILL SEG(RECORD (SEGF) NAME SEG, RECORD (KSEGF) NAME KS, C INTEGER PAR, PDR) SEG_PAR=PAR; SEG_PDR=PDR; SEG_KSL==KS KS_USE=1 KS_PAR=PAR; KS_PDR=PDR KS_DADD=0 END ENDOFPROGRAM REFERENCES 1 F. J. Corbato, C. T. Clingen, J. H. Salter, 'MULTICS, The First Seven Years', Proceedings of the 1972 AFIPS SJCC. 2 Software Engineering, Ed. P. Naur and B. Randell, 1969. 3 W. F. C. Purser, 'The Design of a Real-time Operating System for a Minicomputer', Software Practice and Experience, 5, No 2, 147-167 (1975) 4 F. P. Brooks, 'Mythical Man Month' 5 F. J. Corbato, 'PL/1 as a Tool for Systems Programming', Datamation 15 No. 6, 68-76 (1969) 6 E. I. Organick, 'Computer System Organisation'
7 C. Adams, 'Architecture and Performance Evaluation of EMAS', (To apear in Seminars on Modelling and Performance Evaluation at I.R.E.I.A. 1975) 8 Ferranti, 'Argus 700 Reference Manual' 9 P. Robertson, 'On the Production of Optimised Code from a Transportable Compiler for High Level Languages', (a Ph.D. Thesis to be published). 10 C. Adams and G. E. Millard, 'Performance Measurment on the Edinburgh Multi Access System', Proceedings International Computing Symposium June 1975. 11 P. D. Stephens, 'The IMP Language and Compiler', Computer Journal Vol 17 No 3. 12 H. Whitfield, A. S. Wight, 'EMAS - The Edinburgh Multi Access System', Computer Journal Vol 16 No 4. 13 D. J. Rees, 'The EMAS Director', Computer Journal 14 PDP 11/40 Handbook, Digital Equipment Corporation. 15 D. L. Mills, 'Proposal for a Multi Programming System for a PDP 11', (June 1971). 16 D. L. Mills, 'Multi-programming in a Small Systems Environment', University of Michigan, Technical Report 19. 17 'The UNIX Time Sharing System', Comm of the ACM, Symposium on Operating Systems, October 15-17 1973. 18 R. B. John, 'The design of Systems for Telecommunications between Small and Large Computers', Ph. D. thesis, University of Edinburgh 1973. 19 P. M. Woodwardet. al., 'Definition of CORAL 66', H. M. S. O..
20 I. C. L., 'System B Architecture', SID D100 21 E. W. Dijkstra, 'Co-operating Sequential Processes', Programming Languages (ed. F. Genvys) Acedemic Press 1968. 22 M. M. Barritt et. al., 'The IMP Language Manual', Edinburgh Regional Computing Centre, 1970 23 GEC-Elliott Automation Ltd., Babbage User Manual 1972 24 N. Wirth, 'PL360 A Programming Language for the 360 computers', Journal of the ACM Vol 5 No 1 Jan 1968 25 H. Dewar, 'HAL 7502', Department of Computer Science, Edinburgh University, 1975
ACKNOWLEDGEMENTS There have been too many people who have helped in one way or another and it impossible to mention them all individually. However, specific thanks are due to Dave Mills, Nick Shelness and Professor S. Michaelson who have been very patient and helpful as supervisors, also to Peter Robertson for his IMP compiler, and finally to Dr. J. G. Burns for the encouragement and help he gave to the author.