1
0
mirror of https://github.com/PDP-10/its.git synced 2026-04-03 04:37:53 +00:00

Add most missing SYSDOC files.

This commit is contained in:
Lars Brinkhoff
2017-01-16 18:10:42 +01:00
committed by Eric Swenson
parent 596237d05e
commit 196263051c
16 changed files with 12838 additions and 0 deletions

118
doc/info/netwrk.1 Executable file
View File

@@ -0,0 +1,118 @@
-*-Mode:Text-*-

File: NETWRK Node: Top Up: (DIR)
This file attempts to describe various computer networks of two types --
those to which ITS systems are directly connected, and those which are of
interest to the ITS user community because they link up personal computers or
research institutions that are not accessible by the first kind of network.
There are two networks to which ITS machines are connected: the ARPANet and
the Chaosnet. These networks support file transfer, mail, remote login, and
other services -- they may appear to be quite similar to the user, but have
differing implementations. All the other networks documented herein are
mostly for mail and file transfer.
* Menu:
* ARPANet: (Internet) The Arpanet
* Chaosnet: (CHAOS) The Chaosnet
* User programs for either of the above
* Internet: (Internet) The Internet
* CSNET: (CSNET) The NSF CSnet.
* PCNET: (MC:PCNET;PCNET INFO) Personal Computer Network
Internet
The Internet is a very large computer network that connects various
educational, military, and commericial establishments, all involved in some
way in computer science research. It is actually a ``catenet'' of many
computer networks that run a protocol, the Internet Protocol, to allow
packets to be sent from one host to another, possibly through several other
networks. An accompanying protocol called TCP provides a reliable byte
stream that programs can use, thus ignoring data errors and all the other
nitty-gritty details involved in getting a packet from here to there.
The ARPANet is perhaps the most famous of the Internet networks. It
stretches from Massachusetts to Stanford. Before the days of Internet, it
ran a protocol called NCP, which, unfortunately, was beginning to show its
age. (The ARPANet is at least ten years old.) Because the net had ceased to
become a research project, turning into a heavily-used resource, it was
decided that it would be interesting, now that a long-haul network was shown
feasible, to try to connect various networks together. Then the hosts on
these networks, all differing in one characteristic or another, could talk to
each other without having to contact special hosts that would translate one
high-level protocol into another. IP came out of this desire. (In a false
start, all the internetwork issues were going to be resolved in the TCP
layer, but the details were wisely factored out.) So the ARPANet become
``just another'' network in the Internet, although it still carries most of
the long-distance traffic.
When the switch from ARPAnet to Internet in software was made, it was a
cataclysm underneath, but the user could not notice much. Most of the
high-level protocols used in the NCP days were simply carried over: Telnet,
SUPDUP (where it was implemented), FTP, and SMTP. Some ITS user programs
contain commands to switch from TCP to NCP mode, though this is not usually
required.
At MIT, Internet appears in a variety of ways. First, there is the ARPANet.
The second type of network to embrace IP was the LCS/Pronet Ring net. The
main users of these networks are the LCS VAXes and many of the Athena
machines. Thirdly, there are Ethernets at Tech Square who run IP, usually
along with Chaosnet. The users of this mode include some VAXes at the AI
Lab, and some LCS machines. And last, but not least, the Chaosnet can also
support Internet (after much heated discussion). A few Unix machines have
taken this option.
As for the ITS machines, they all connect to the Internet through their
ARPANet IMPs. The Internet host tables can be found in SYSENG; HSTNIC >
ITS implements both server and user programs for FTP, TELNET, and SUPDUP.
The MLDEV is also supported. There is also an SMTP (mail) server. Sources
for various TCP-related programs can be found in the TCP; directory on MC.
For programmers, there is a quick rundown of the ITS TCP interface (and
documentation that applies to network system calls in general) in
TCP;TCPDOC > The network status can be checked with the PEEK program.
CHAOS
The Chaosnet was developed at the MIT AI lab as a local network to allows
Lisp Machines (CADRs, specifically) to access files on AI and MC. Its
success caused it to become the most widely used local network at MIT. The
following operation systems have support Chaosnet: LispM, ITS, Twenex, Tenex,
Unix, Multics, VMS, Seconds, MINITS, and MOS. The last three are used
mainly in terminal concentrators and bridges. Chaosnet has also been used at
Yale, TI, and many other Lisp Machine installations. The definitive Chaosnet
documentation can be found in AI Memo 628, ``Chaosnet,'' by David Moon.
Chaosnet started out being supported by special Chaosnet hardware, but is now
mostly used with Ethernet II hardware. Leased serial lines and microwave
links have also been used to run Chaosnet. It is stressed that Chaosnet is
local network, but it has been used with some success transcontinentally.
On ITS, most programs (except FINGER) will automatically chose to use the
Chaosnet. Here is a list of current user and server programs:
Service Protocol User Server
--------------------------------------------------------------
Remote Login TELNET :TELNET yes
SUPDUP :SUPDUP yes
File Access FILE :CFTP yes
Mail MAIL (COMSAT) yes
SMTP (COMSAT) yes
TTY send SEND :SEND yes
CONVERSE
There are also the usual servers for HOSTAB, TIME, UPTIME, and STATUS. All
ITS machines offer a TCP server as well -- it allows Chaosnet hosts to
contact Internet hosts at a specified port number. There is also a GMSGS
server and a LIMERICK server.
For contacting a host at an arbitary contact name, use
:MOON;CHARFC host contact
The K PEEK mode will show that status of the Chaosnet.

1
doc/sysdoc/-read-.-this- Executable file
View File

@@ -0,0 +1 @@
This directory (SYSDOC) contains system documentation for ITS.

2184
doc/sysdoc/chaord.57 Executable file

File diff suppressed because it is too large Load Diff

760
doc/sysdoc/chaos.file Executable file
View File

@@ -0,0 +1,760 @@
-*- Mode:Text -*-
Description of the CHAOS FILE protocol designed by HIC.
The CHAOS FILE protocol is a protocol used to give access to the
file systems of remote hosts on the CHAOS net. Provided that the
foreign host has a CHAOS FILE server, one can read and write files,
delete, rename, etc. The protocol was originally designed to give LISP
machines access to the file systems of our PDP/10's, but is general
enough to support file transfer between 10's, and other purposes.
We will describe the protocol from the point of view of the
user, i.e., the implementor of a user program communicating to a foreign
server. Hence, terms such as "receive", "send", "input", and "output"
are from a user's point of view, unless explicitly indicated. The first
step in using the protocol is to open what is called a CONTROL
connection to the server on the foreign host. A CONTROL connection is
simply a standard CHAOS net connection to the contact name "FILE" on the
foreign host. The CONTROL connection is used to send commands, and
receive responses and most error message.
When reading or writing files, actual data is sent over separate
CHAOS net connections called DATA connections. DATA connections are
opened in conjunction with the foreign host, using commands on the
CONTROL connection. Hence, the CONTROL connection must be opened first.
We will present the details below; but here are some preliminary facts
about DATA connections. Like CONTROL connections, DATA connections are
bidirectional. Each half (send and receive) of a DATA connection is
used independently, so two file transfers may be active on a DATA
connection at the same time (but they must be in opposite directions).
There may be more than one DATA connection per CONTROL connection, but
each DATA connection is associated with a particular CONTROL connection.
This is because each CONTROL connection deals with a separate
incarnation of the server at the foreign host. We also note that DATA
connections are re-usable, i.e., can be used for many file transfers.
Simple programs might very well get by with a single DATA connection,
but it is possible to have several (the actual limit depends on
resources of the foreign host, and is 3 for ITS servers, and 8 for
TOPS-20 servers).
The protocol is organized so that commands and responses have a
fairly uniform syntax. Further, each command (response) is sent
(received) in a single packet. Each command has a field for a unique
identifier, called the transaction id, or "tid" for short, which
identifies it. This is because the protocol permits asynchronous
processing of commands and responses, i.e., you can send a new command
without waiting for the response to the previous one. However, it is a
good idea to read the responses as they come in, so the server will not
block trying to send responses to you. The server is coded so that it
will not block if DATA connection packets back up.
Let us now discuss the details of command and response packets.
We will discuss error processing later. Each command must be sent in a
separate packet on the CONTROL connection. The packet must have the
packet opcode for ASCII data (%CODAT = 200). When you are done with the
CONTROL connection and wish to disconnect from the foreign host, you
should send an EOF packet (%COEOF = 014) on the CONTROL connection.
This will cause the server to abort any transfers in progress, close all
DATA connections pertaining to this CONTROL connection, and close the
CONTROL connection.
Responses to commands, successful or not, will come as data
packets (i.e., opcode %CODAT) on the CONTROL connection. The only other
kind of packet you should see on the CONTROL connection (unless there
are network problems) and asynchronous mark packets, which will be
discussed later.
The contents of a command or response packet is simply the
sequence of ASCII bytes in the data portion of the packet. Fields are
generally separated by either spaces (040) or LISP machine newline
characters (NL = 215). We remark now that certain parts of the protocol
are oriented towards the LISP machine character set, which consists of
256 characters. This is in contrast to the 128 character set standard
on PDP/10's. The printing characters generally have the same
interpretation, though. Later we will explain the character set
translation features provided by the protocol in detail.
Here is the format of command and response packets:
command: tid <sp> [ fh ] <sp> cmd [ args ]
response: tid <sp> [ fh ] <sp> cmd [ <sp> results ]
<sp> means a space character (040), and brackets surround
optional fields. Each field is a sequence of printing characters. Here
is the interpretation and format of the common fields:
tid: Transaction identifier, used only to help the user program sort
out replies. Only the first 5 characters are significant; the
rest are discarded, and will not appear in a response. Tid's
may vary or be the same, as you wish.
fh: File handle, used to identify a DATA connection, and a direction
(in/out). That is, each DATA connection has two file handles
associated with it, one for indicating input (transfer to you
from the foreign host), and one for output (transfer from you to
the foreign host). Like tid's, file handles are also unique
only in the first 5 characters.
cmd: A command name. Only the first 5 characters are actually read
at the current time, but this should not be depended upon. The
full name of the command always appears in the response.
Command names must be presented in upper case.
The "args" and "results" fields vary depending on the command,
and will be described with each command below. The response to a
particular command will have the same tid as the command, and also the
same file-handle (if relevant), and the same command name. The only
differences are that the tid and file handle in the response will be
truncated to 5 characters, and the command name will always appear in
full.
Conventions used in the descriptions:
Numbers we write (e.g., packet opcodes, ASCII codes, etc.) are
in octal, unless followed by a decimal point, in which case they are
decimal. Byte sizes are an exception to this rule: they are always in
decimal, even if not followed by a decimal point.
<none> means an empty field in a packet.
<num> means a sequence of ASCII characters that are all digits
(codes 060 through 071, i.e., '0' through '9'). Such numbers are always
expressed in decimal. These numbers are unsigned, but may have leading
zeroes. (The server may possibly send a negative <num> to you, e.g.,
the "-1" of the version field of an OPEN response, but you should never
send a negative <num> to it.)
Some syntax was too long to be presented on a single line here;
we note that there is no CRLF or newline in the packet when we continue
syntax on a second line. That is, all characters in every command or
response are written down explicitly.
A reminder: the end of a command or response is not marked by a
special character, because the length field of the CHAOS net packet
determines where the data ends.
------------------------------------------------------------------------
DATA-CONNECTION
args = <sp> ifh <sp> ofh
results = <none>
This is used to open a new DATA connection. The "ifh" and "ofh"
fields are the input and output file handles to associate with this data
connection. Each should be distinct from all other file handles of
other DATA connections pertaining to the same CONTROL. Since this
command does not pertain to any existing file handles, the file handle
field of the command must be omitted. As would be expected, the input
file handle is used to describe the receive half of the DATA connection
and the output file handle is use to describe the send half.
When the server receives a valid (well-formed, etc.)
DATA-CONNECTION packet, it will attempt to open a new CHAOS net
connection to your host, using "ofh" (the output file handle you
supplied in the command packet) as the contact name. Hence, you should
listen for such a connection. The server will respond to the
DATA-CONNECTION command immediately, even though the new DATA connection
may not yet be open. Of course, you cannot use the connection until it
is open, but you will know that, because you had to open it.
------------------------------------------------------------------------
UNDATA-CONNECTION
args = <none>
results = <none>
This command is used to close a DATA connection when you are
finished with it. There is probably little occasion to use this, since
any DATA connections will be closed when the CONTROL connection is
closed, and a DATA connection can be re-used for multiple file
transfers. The DATA connection closed is the one whose input or output
file handle appears in the file handle field of the UNDATA-CONNECTION
command. UNDATA-CONNECTION implies a CLOSE on each file handle of the
DATA connection for which there is a file transfer in progress.
------------------------------------------------------------------------
OPEN
args = [ options ] <NL> filename <NL>
options = <sp> option1 <sp> option2 ... <sp> optionN
results = <sp> version <sp> date <sp> len <sp> qfasl
<NL> realname <NL>
This command is used to open a file for reading or writing at
the foreign host. The "filename" part is the filename to use at the
foreign host. It is always expressed in the foreign host's file name
syntax. The "options" field will be explained momentarily. If an input
file handle is given in the file handle field of the command, then the
file is to be opened for reading. If an output file handle is given,
then the file is to be opened for writing. In either case the file
handle serves to indicate not only the direction of transfer, but also
the DATA connection to be used for the transfer. A file handle must be
supplied, unless a PROBE is being done. PROBE will be explained below,
but breifly, it permits you to find out information about a file (i.e.,
the "results" information of an OPEN response) without actually opening
it.
The "options" field of the OPEN command consists of a number of
options (most of them are simple ASCII strings), always in upper case,
each preceded by a space (to separate them from the "OPEN" and from each
other). The options permit you to specify whether the transfer is to be
BINARY or CHARACTER, and a number of other things. Some options apply
only to BINARY transfers, and others (character set translations in
particular) only to CHARACTER transfers. Here is a list of the options
and their meaning.
READ - Indicates that we will be reading a file. This is
redundant, and is checked for consistency (i.e., we must have
given OPEN an input file handle).
WRITE - Analogous to READ.
CHARACTER - Specifies that we will be transferring character
data as opposed to binary. This affects the mode in which the
server will open a file, as well as whether or not character set
translations are performed. CHARACTER is the default, so it
need never be specified. The check for QFASL files is not
performed (see below).
BINARY - Specifies that we will be transferring binary data. A
check is made for QFASL files when reading (the result of the
test is supplied in the response to the OPEN; see below). The
default byte size is 16 bits (see the discussion of byte sizes
below).
PROBE - This is used to check the existence of a file, and find
out information about it if it exists. The file is not actually
opened. This option is implied if no file handle is given in
the OPEN command. You should not supply a file handle when
doing a PROBE. The response packet will contain the same
information as a response to OPEN'ing the file for reading.
BINARY vs. CHARACTER makes a difference in a probe, as described
in the discussion of the response to OPEN.
Options pertaining to BINARY transfers only:
BYTE-SIZE <sp> <num> - Specifies to use bytes with <num> bits
each. The interpretation is explained below.
Options pertaining to CHARACTER transfers only:
RAW - Suppresses character set translation (see below).
SUPER-IMAGE - Suppresses rubout quoting (this pertains to
character set translation, see below).
Options specific to particular foriegn hosts:
At present there are only two kinds of servers: ITS servers
(e.g., AI and MC) and TOPS-20 servers (e.g., XX, EE, and SPEECH). There
are two options that are specific to TOPS-20 servers (i.e., they do not
work for ITS servers, and should not be presented to them):
TEMPORARY - TOPS-20 server only: says to use GJ%TMP in the
GTJFN. This is useful mainly when writing files, and indicates
that the foreign operating system is to treat the file as
temporary. See TOPS-20 documentation for more about the
implications of this option.
DELETED - TOPS-20 server only: says to set GJ%DEL in the GTJFN.
This is useful mainly for READ'ing or in PROBE's, and indicates
that deleted files should be considered when looking for a file.
See TOPS-20 documentation for information about this.
Details for ITS servers:
A CHARACTER OPEN will be in .UAI (.UAO) mode when reading
(writing). Similarly, a BINARY OPEN will be in .UII (.UIO)
mode. An OPEN for writing always opens _LSPM_ OUTPUT in the
spcified directory, but does a RENMWO just before the CLOSE, to
the appropriate file names. The server takes care of the
traditional screws associated with the last word of text files,
i.e., you don't have to worry about it -- you will never see the
extra characters.
Details for TOPS-20 servers:
GTJFN's - When OPEN'ing for READ or PROBE, GJ%OLD is always set.
When OPEN'ing for WRITE, GJ%FOU and GJ%NEW will be set. These
are independent of the setting of GJ%DEL and GJ%TMP (see the
TEMPORARY and DELETED options, above).
OPENF's - CHARACTER mode does a 7-bit OPENF, normal mode, with
line number checking off when reading. BINARY mode does a
36-bit DUMP mode OPENF -- the server handles the packing and
unpacking of bytes within words.
Open results:
results = <sp> version <sp> date <sp> len <sp> qfasl
<NL> realname <NL>
version = a <num>, expressing the version number of the file.
On ITS server, this will be the numeric second name, or the
leading numeric characters of the second name. If the name has
no numerics, the field will be "-1". On TOPS-20 this will be
the generation number of the file.
date = The creation date of the file, expressed in the form
"mm/dd/yy hh:mm:ss". (That is a real <sp> between the date and
the time.)
len = ASCII digits for the length of the file in the byte size
being read. This will always be 0 when writing.
qfasl = "T" if we are doing a BINARY READ, and the first word
of the file is "QFASL" in sixbit. "NIL" otherwise. This is
clearly oriented towards LISP machines!
realname = the full name of the file, e.g., what RFNAME (on ITS)
or JFNS (on TOPS-20) will tell you, when asking for all the
usual fields (device, directory, first name, second name,
generation number).
------------------------------------------------------------------------
CLOSE
args = <none>
results = <sp> version <sp> date <sp> len
<NL> realname <NL>
A file handle must be given, and a transfer must be active on
that handle. A synchronous mark will be sent or awaited accordingly,
and the file will be closed (but not the DATA connection). See the
discussion of data transfer protocol, below, for more details.
The results are mostly as for OPEN. However, the "len" field is
computed differently. For ASCII input, it will be the number of
characters, as returned by FILLEN on ITS. On TOPS-20, it will be the
number of bytes in the file, if it was written using 7-bit bytes,
otherwise, 5 times the number of words. For binary input, it is the
number of words in the file times 2. For ASCII output, "len" is the
exact number of characters written, and for binary output, it is the
number of words times the number of bytes per word for the current byte
size. [This stuff may be buggy anyway.]
------------------------------------------------------------------------
FILEPOS, args = <sp> <num>
This must have a file handle, and it must be an input file
handle. It requests the foreign host to reset its file access pointer
to byte <num> of the file currently open, according to the current byte
size being used. As explained below, this sends a synchronous mark
before starting to send more data. FILEPOS is ILLEGAL for files being
written.
------------------------------------------------------------------------
DELETE
args = <none> or <sp> filename <NL>
results = <none>
If a file handle is given the file being read or written on the
specified DATA connection will be deleted after we close it (regardless
of direction). The file handle must refer to an open DATA connection,
and the direction must be correspond to the current transfer. This is
called a "delete while open", or DELEWO. In such a case, DELETE should
have no argument.
If no file handle is given, then the optional argument must be
present, and specifies a file to be deleted immediately.
------------------------------------------------------------------------
RENAME
args = <NL> filename1 [ <NL> filename2 ] <NL>
results = <none>
If a file handle is given, only the first filename should be
present, and the file will be renamed to filename1 sometime. This is
called a "rename while open", or RENMWO. On ITS, a RENMWO call is done
immediately. On TOPS-20, a GTJFN is done to filename1, and when we do a
CLOSE on the file handle, the CLOSF is done with CO%NRJ set, and then an
RNAMF is done to the previously obtained jfn.
If no file handle is given, then both filenames must be present,
and the effect is to rename filename1 to be filename2. Don't forget
that on ITS renaming can only be done within a directory. The server
simply ignores the device and directory parts of filename2, so be
careful. On TOPS-20, renaming from one pack to another will fail.
------------------------------------------------------------------------
CONTINUE
args = <none>
results = <none>
This must have a file handle, and the indicated channel must be
in the asynchronously marked state. That is, an error of some kind
occurred. If the error might be recoverable, then CONTINUE will try to
resume from it. If the error is non-recoverable, you will get an error
response. See the discussion of marks below.
------------------------------------------------------------------------
SET-BYTE-SIZE
args = <sp> nbs <sp> [ npos ]
results = <none>
This must have a file handle, which must refer to a file open in
BINARY mode. Both nbs and npos are <num>'s. "nbs" is the new byte
size, and must be in the range 1 to 16. "npos" is the new position in
the file IN TERMS OF THE OLD BYTE SIZE. The npos part may be omitted
for output files, and is ignored if present (but the second <sp> MUST be
there). If npos is omitted for input files, it defaults to 0. This
command sends or awaits a synchronous mark.
------------------------------------------------------------------------
LOGIN
args = <NL> userid [ <NL> password [ <NL> account ]]
results from ITS = <sp> uname <sp> hsname
<NL> persname <NL>
results from TOPS-20 = <none>
This command is for logging in at the foreign host. You must
log in before any OPEN commands will be accepted. Logging in to ITS is
simple: you just give the desired UNAME, which may even legally be
blank. On TOPS-20, the userid must correspond to a real directory
(RCUSR is used), and the password and account are passed to a LOGIN
jsys. For most of our TOPS-20's, userid = ANONYMOUS and password =
ANONYMOUS will give you a login of low privilege. If the first character
in the password is an asterisk, capabilities will be enabled.
------------------------------------------------------------------------
DIRECTORY
args = options <NL> pathname
results = same as for OPEN
The only option currently allowed is DELETED, which says to include deleted
files (TOPS20) or "*" files (ITS).
The DIRECTORY command is like opening an input file. The possible responses
are the same as for OPEN, except that the affirmative response says DIRECTORY
rather than OPEN.
The input file that you read consists of a series of records; first a
header and then the name and properties of each file that matches the
pathname, which may contain wildcards in system-dependent fashion. Each
record read consists of a pathname, <NL>, a set of properties separated by
<NL>, and an extra <NL> to separate it from the next record. Each property
consists of the name of the property, optionally followed by a space and
the value. (If no value is present, the property is a yes/no property and
the value is yes). The header record is in the same format; it has a blank
pathname and has the properties for the file system as a whole rather than
for a particular file.
The properties are not documented here; consult the Lisp machine manual for
a list of the most useful ones.
------------------------------------------------------------------------
COMPLETE
args = options <NL> default-pathname <NL> string
results = status <NL> new-string <NL>
This does filename completion. String is a filename typed in by the user
amd default-pathname is the default name against which it is being typed.
The filename is completed according to the files present in the file system
and the possibly-expanded string is returned.
Allowed options are DELETED, READ, WRITE, OLD, NEW-OK. DELETED means not
to ignore deleted files; this applies to Tenex and TOPS-20 only. READ
means the file is going to be read (this is the default). WRITE means the
file is going to be written, and affects version number defaulting. OLD
means an existent file is required (this is the default). NEW-OK means that
it is permissible for the string to complete to the name of a file that does
not exist.
The returned status is NIL, OLD, or NEW. NIL means that an error occured,
OLD means that the string completed to the name of an existent file, NEW
means that the string completed to a legal filename which is not the name
of an existent file.
------------------------------------------------------------------------
CHANGE-PROPERTIES
args = filename <NL> property-name <SP> new-value <NL> ...
results = <none>
This allows you to change one or more properties of a file. The properties which
are legal to change are those in the SETTABLE-PROPERTIES property of the header
record returned by the DIRECTORY command. The legal values for yes/no
properties are T and NIL.
------------------------------------------------------------------------
About character set translations:
As mentioned somewhere above, the protocol was originally
designed to provide access to PDP/10 file systems for LISP machines.
LISP machines support 8-bit characters, and hence have 256 characters in
their character set. This results in minor difficulties when conversing
with PDP/10's, which prefer 7-bit characters. Translations apply ONLY
to CHARACTER transfers, not BINARY transfers. Below is a table showing
the "normal" (i.e., default) correspondence between LISP machine and
PDP/10 characters. Some LISP machine characters expand to more than one
PDP/10 character. The notation "x in <c1, c2>" means "for all
character codes x such that c1 <= x <= c2."
LISP machine character PDP/10 character(s)
x in <000, 007> x
x in <010, 012> 177 x
013 013
x in <014, 015> 177 x
x in <016, 176> x
177 177 177
x in <200, 207> 177 <x - 200>
x in <210, 212> <x - 200>
213 177 013
214 014
215 015 012
x in <216, 376> 177 <x - 200>
377 no corresponding code
This table may seem confusing at first, but there ARE some
general rules about it that should make it appear more sensible. First,
LISP machine characters in the range <000, 177> are generally
represented as themselves, and x in <200, 377> is generally represented
as 177 followed by <x - 200>. That is, 177 is used to quote LISP
machine characters with the high bit on. It was deemed that 177 is more
important than 377, so 177 177 means 177, and there is no way to
describe 377 with PDP/10 characters. On the LISP machine, the
formatting control characters appear shifted up by 200. This explains
why the preferred mode of expressing 210 (backspace) is 010, and 010
turns into 177 010. The same reasoning applies to 211 (tab), 212
(linefeed), 214 (formfeed), and 215 (newline). However, newline has an
added twist -- it is supposed to start at the beginning of a new line,
so it is deemed equivalent to 015 012 (CRLF) in PDP/10 characters. When
converting PDP/10 characters to LISP machine characters, an 015 always
turns into a 215; however, if it is followed by an 012, the 012 is
skipped.
The above table applies in the case of NORMAL translation, i.e.
the default translation mode. Note that the server ASSUMES the user is
a LISP machine, and that all our servers are PDP/10's, so the labellings
"LISP machine" and "PDP/10" can be thought of as "user" and "server".
The other translation modes available are:
RAW - perform no translation (PDP/10 characters simply discard
the high order bit of LISP machine characters, and LISP machine
characters supplied by a server will always be in the range
<000, 177>.
SUPER-IMAGE - This suppresses the use of rubout for quoting.
That is, each entry beginning with a 177 in the PDP/10 column of
the translation table presented above, has the 177 removed. The
PDP/10 character 015 always maps to the LISP machine character
215, as in normal translation. Here is the corrected table:
LISP machine character PDP/10 character(s)
x in <000, 177> x
x in <200, 214> <x - 200>
215 015 012
x in <216, 376> <x - 200>
377 no corresponding code
User programs written for PDP/10's probably do not wish to have
any of the above translations performed, since they are using the PDP/10
7-bit character set. Hence, RAW is probably what you want. It is also
the most efficient method of transferring ASCII data using the protocol.
----------------------------------------------------------------
Data transfer and byte packing issues:
Once a DATA connection has been established, and an OPEN has
succeeded, data transfer proceeds by sending/receiving packets on the
appropriate DATA connection. CHARACTER data is always in packets with
opcode %CODAT (200), and BINARY data in packets with opcode 300 octal.
Consider the data portion of a packet as a sequence of 8-bit bytes, in
the fashion usual for the CHAOS net. Then CHARACTER data is always
packed one character per packet byte. The organization is such that a
standard PDP/10 byte pointer of size 8-bits can be used to load or store
characters into a packet sequentially. (As usual, the low 4 bits of
each 36-bit word is ignored, and not even transmitted on the CHAOS net.)
There are no particular restrictions on the minimum or maximum sizes of
data packets, other than hardware or operating system limits. The
server will always send the largest packets it can.
The situation with BINARY data is slightly more complicated. We
must consider the data portion of a packet as a sequence of 16-bit
bytes. Each 16-bit byte consists of two 8-bit bytes, with the first of
the two 8-bit bytes being the high-order half of the 16-bit byte. (This
corresponds to PDP/10 conventions, but is the opposite of PDP/11
conventions regarding byte packing.) Each byte of binary data sent is
stored in one 16-bit byte in the packet. If the byte size is less than
16-bits, then the byte is right-justified within the 16-bits, with the
remaining high order bits set to unpredictable values. The organization
is such that loading or storing sequential bytes in a packet can be done
with a standard PDP/10 byte pointer of byte size 16 bits, and transfer
of the bytes so obtained to or from words of files can be done with a
byte pointer of the size in use for the transfer.
Each packet of BINARY data should contain an integral number of
16-bit bytes, i.e., it should have an even nmber of 8-bit bytes. If it
does not, the odd byte is discarded. The server always sends binary
packets with an even number of 8-bit bytes.
For transferring all 36 bits of a PDP/10 word to another 36 bit
machine, the byte size must divide 36. The most efficient value is 12,
since it is the largest divisor of 36 that is not greater than 16, which
is the largest byte size supported by the protocol.
----------------------------------------------------------------
Protocol issues in data transfer:
In addition to just data packets, some other kinds of
informative packets are sent or received on the DATA connection.
EOF packets (opcode 014) are used to mark end of file when
reading or writing. That is, when you are writing a file and come to
the end of what you wish to write, you will send an EOF packet to tell
the server it has reached the end. Similarly, you will receive an EOF
packet at the end of a file when reading. EOF packets are always empty
(i.e., contain no data). There are additional details about closing a
file, however; read on.
In addition to EOF packets, SYNCHRONOUS MARKS (opcode 201) are
used to separate groups of packets in the transfer, mainly for purposes
of matching up with FILEPOS and SET-BYTE-SIZE commands. You will
receive a synchronous mark on the DATA connection sometime after each
successful FILEPOS and SET-BYTE-SIZE command. These marks indicate the
place in the data stream where the command actually occurred. They are
necessary because the server may be several packets ahead of you in
sending data, and without the marks there would be no easy way to tell
where the previous information ended and the new information starts. A
synchronous mark is also sent in response to a CLOSE command when
reading, and expected after an EOF when writing. The mark after a CLOSE
when reading allows you to find the end of the data packets for that
transfer, if you decide to stop the transfer in the middle. The mark
after EOF when writing performs a similar function for the server if you
terminate the transfer in the middle.
When writing, you should send a synchronous mark on the DATA
connection whenever you perform a successful SET-BYTE-SIZE command, and
also as part of a CLOSE, as described above. All other synchronous
marks are ones that you will receive.
Examples:
1) Reading a file. Assume you have a CONTROL connection and an idle
DATA connection. Send an OPEN command, and await the response. Then
start reading data packets from the data channel. The transfer will
continue unless you stop it. Suppose you have read all the file. Then
you will see an EOF packet. Send your CLOSE command, to order the file
closed, and await a SYNC mark on the DATA connection, indicating that
the close is in fact done, and the DATA connection can be re-used for
some other purpose. If you decide to quit in the middle, send a CLOSE
command, and get the response, and read packets from the DATA connection
until you see a SYNC mark. (This assumes that there would be no other
SYNC marks in transit because of, say, a previous FILEPOS command, etc.
If there were any of those, you will have to wait through the
appropriate number of SYNC marks.)
2) Writing a file. Again assume you have established a CONTROL and DATA
connection. Send the OPEN command and await the reponse. Then start
writing packets on the DATA connection. Assuming there are no problems,
send an EOF. WAIT FOR THE EOF TO BE ACKNOWLEDGED BY THE SERVER. (That
is, a CHAOS net acknowledgement indicating that the server has actually
read the EOF packet.) Now send a SYNC mark on the DATA connection and a
CLOSE on the CONTROL connection (in either order). If you do not wait
for the EOF to be acknowledged, and you send a CLOSE anyway, the file
may be truncated because some data packets may not have been processed
by the server.
----------------------------------------------------------------
Errors and Ansynchronous marks:
ASYNCHRONOUS MARK packets (opcode 202) indicate error conditions
in the transfer, such as running out of disk space or allocation. Some
of these may be recoverable, some not. When reading, an asynchronous
mark will come in over the appropriate DATA connection. When writing,
it will come in on the CONTROL connection. (The DATA connection is not
used in this case because the receive half might be in use for another
transfer). Here is the format of an asynchronous mark packet:
tid <sp> fh <sp> ERROR <sp> erc <sp> c <sp> message
That is, it looks like a regular error response packet, except that it
has a different opcode (responses are data packets, opcode 200). The
tid should be ignored -- it will be somewhat random (whatever happens to
to be lying around). The file handle, fh, is useful when writing, to
see which DATA connection the error happened to. The "erc" part is a 3
character error code (a table of them is presented below, subject to
change without notice). The single character "c" will be either "R"
(for recoverable) or "F" (for fatal). A recoverable error can be
restarted from by sending an appropriate CONTINUE command. A fatal
error cannot be recovered from, and an appropriate CLOSE should be
performed. The "message" part is an ASCII error message, possibly
obtained from the host operating system.
Error codes:
Flag codes:
C = command error (comes in data packet with cmd = "ERROR", on
the CONTROL connection).
F = fatal asynchronous error.
R = restartable asynchronous error.
Flag Code Message, Causes, Possible Diagnosis
C CCC - CHANNEL CANNOT CONTINUE
CONTINUE not possible.
C CNO - CHANNEL NOT OPEN
CLOSE on non-open channel.
C CRF - CANNOT RENAME OUTPUT FILE TO REAL NAMES
Final RENMWO for CLOSE on ITS failed.
F CSP - CANNOT SET POINTER
Response to this failure in FILEPOS or SET-BYTE-SIZE.
C FNF - message varies, depending on reason (FILE NOT FOUND).
Failing OPEN.
C IBS - ILLEGAL BYTE SIZE
Response to byte size not in range 1 - 16.
F IDO - ILLEGAL DATA OPCODE
Bad packet opcode in the range 200 - 377 (you should use
200 for CHARACTER data, and 300 for BINARY)
C IFH - ILLEGAL FILE HANDLE FOR FILEPOS
Only input file handles are legal.
R IOC - message varies (INPUT OUTPUT CONDITION).
Generic code for possibly recoverable failures. This
will be sent in an ASYNC mark packet.
F IPO - ILLEGAL PACKET OPCODE
Received a packet with an illegal opcode, or a SYNC or
ASYNC mark when not expected.
C IRF - ILLEGAL REQUEST FORMAT
Generic response to ill-formed command.
C ISC - ILLEGAL CHANNEL FOR SET-BYTE-SIZE
SET-BYTE-SIZE may only be done on BINARY channels.
C NCN - NULL COMMAND NAME
Particular case of a bad command.
C NER - NOT ENOUGH RESOURCES
Possible causes are: no more I/O channels/jfns available
for new DATA connections, system failure to open a new
CHAOSnet channel, and inability to lookup a user's info
in LOGIN.
C NLI - NOT LOGGED IN
OPEN cannot be done until you are logged in.
C TMI - TOO MUCH INFORMATION
This happens if a response or error packet overflows.
C UFH - UNKNOWN FILE HANDLE
Particular case of an ill-formed command.
C UKC - UNKNOWN COMMAND
Particular case of an ill-formed command.
C UNK - USER NOT KNOWN
Bad LOGIN (TOPS-20 only).
C UOO - UNKNOWN OPEN OPTION
Obvious problem.
F xxx - ??? When a file system or other operating system call
fails, which is not covered in the above, then another code is
used. These are taken from a table for ITS, with the message
read from the ERR: device, and on TOPS-20, the letters are the
first letters of the first three words of the error message
returned by an ERSTR call. The only exception is code FNF,
special cased if the error is GJFX24 ("file not found") or OPNX2
("file does not exist") on TOPS-20. No other FNF's will come
from TOPS-20, even by "accidient" -- a special check is made.

169
doc/sysdoc/clo.100 Executable file
View File

@@ -0,0 +1,169 @@
-*-Text-*- Alan 12/31/83
Here is what I know about the core link device(s).
The core link device is a primitive mechanism for connecting two jobs
together with a uni-directional stream. The basic idea is very simple:
suppose job A opens CLO:FOO;BAR BAZ for input and job B opens
CLO:FOO;BAR BAZ for output, then by virtue of the fact that they used the
same name (FOO;BAR BAZ) they are connected together and anything job B
happens to output to its channel will be what job A reads from its channel.
For many simple hacks, that's all you really need to know about it!
The core link device is not a random access device. Only the most basic
system calls are supported (like OPEN, IOT, SIOT, STATUS, RFNAME, and
CLOSE). There is no way for either job to cause the other to receive a
second word interrupt. For more advanced applications where a more
complicated interface is desired the JOB device can be used. See
.INFO.;ITS JOBONL (or .INFO.;ITS JOB).
ITS keeps an I/O buffer for each core link, so the two jobs will not
actually be kept running in lock-step. The outputting job will wait when
it tries to output only if the buffer becomes full, and the inputting job
will wait when it tries to input only if the buffer becomes empty. The
buffer is about 100. words long. Because of this buffering it is not
necessary for both jobs to open their channels in identical modes, one job
can read (write) 36-bit words while the other is writing (reading) 7-bit
characters. [This should be contrasted with the JOB device, where ITS
cannot keep any internal state for the JOB/BOJ connection because of
PCLSRing considerations.]
If the reading job closes its input channel, the writing job's output
channel acts like the NUL device. All output is simply discarded. If the
writing job closes its output channel, the reading job's input channel acts
like it has reached end of file (after it has read whatever remained in the
buffer of course). [Actually, in .UII mode if you IOT beyond end of file
it starts returning random 36-bit words. It should be fixed to generate an
IOC interrupt like other devices do at EOF in .UII mode. I guess it really
doesn't matter much since you don't open things in image mode unless you
know exactly what they are anyway...]
There are actually 4 core link devices: CLO (Core Link Open), CLU (Core
Link Use), CLI (Core Link Interrupt), and CLA (Core Link Answer). The
differences between them all have to do with what happens when you open
them. In fact, after you have completed the process of opening a channel
with any of these devices, an RFNAME call on that channel will always
report that it is the CLO device, since from that point on they all behave
identically.
In order match up jobs that desire to use the core link device, ITS
maintains a table called the "core link directory". At any given time the
core link directory contains a number of "core links". Each core link has
three names: an SNAME, a first name, and a second name (SNAME;NAME1 NAME2).
When a job tries to open CLO:FOO;BAR BAZ, ITS searches the core link
directory for a core link named FOO;BAR BAZ. If no core link is found with
that name, then a new core link is created with that name and entered in
the directory. (If the core link directory gets full a %EFLDR error can be
returned at this point.)
The CLU device behaves identically to the CLO device, except that if no
existing core link has the proper name then instead of creating a new one,
a file not found error is returned (%ENSFL). Thus you should use the CLU
device when you are certain that some other job has already created a core
link of a given name.
Also potentially associated with each core link is a pair of jobs. One for
reading, and one for writing. After an appropriately named core link has
been located or created, ITS checks to see whether some other job already
has this core link open in the same direction. If so, a file locked error
is returned (%ENAFL), otherwise this job is recorded as the one reading or
writing the core link, and the channel is successfully opened.
You can list the core link directory. Opening CLO:.FILE. (DIR) will
allow you to read a table like the following:
SNAME NAME1 NAME2 ALAN A -> ALAN B
SPAZM FOOBAR 259 CLOSED-> ALAN A
QAZWSX FOOBAR 259 ALAN FOOBAR-> CLOSED
FOO BAR BAZ CLOSED-> CLOSED
(Try typing CLO^F to DDT. Probably the core link directory will be empty,
so you won't seen anything interesting.)
This table is interpreted as follows:
SNAME NAME1 NAME2 ALAN A -> ALAN B
^ ^ ^ ^ ^ ^ ^
| | | | | | | UNAME and JNAME of
| | | | | +------+--- job reading from
| | | | | this core link.
| | | | |
| | | | | UNAME and JNAME of
| | | +------+---job writing into
| | | this core link.
| | |
| | | SNAME and first and
+------+------+---second names for
this core link.
If no job is reading from the core link, the word CLOSED will appear after
the arrow instead of a UNAME/JNAME pair. Similarly if no job is writing
into the core link, CLOSED appears before the arrow.
If you are trying to debug something that uses the core link device, a
listing of the core link directory is a valuable debugging aid.
In the core link directory listing above, the core link named FOO;BAR BAZ
has neither an associated reading nor writing job. You might think that
such a core link would be worthless, but this is not necessarily the case!
Suppose that job A opens CLO:FOO;BAR BAZ for output intending to only
transmit 100. ascii characters through the link. Since 100. characters can
easily fit in the core link's buffer, job A can output all 100. characters
and close its channel before the reading job even gets as far as opening
its channel. Thus for a brief time the core link has no associated jobs.
Unfortunately there is no way to guarantee that any job will ever open the
core link FOO;BAR BAZ for input to pick up those 100. characters. For this
reason ITS will garbage collect any core link that has not had any
associated jobs for several minutes (about 5 minutes).
You can also delete core links from the core link directory yourself. Thus
from DDT you can type "^O CLO:FOO;BAR BAZ" to get rid of a garbage core
link. Normally there is no need to do this, since ITS will flush them
eventually anyway. [Indeed, it is a BAD idea to use this feature currently
because there is a bug such that instead of deleting the core link, you
sometimes cause it to become permanently locked down. Since there are a
finite number of core links (12. currently), if you do this often enough
you will render the core link device unusable.]
A reasonable person might wonder what happens if some job tries to re-open
the core link FOO;BAR BAZ for output and write more characters into it.
Well, each core link actually acts as a SEQUENCE of files separated by
end-of-file markers. If a second job opens CLO:FOO;BAR BAZ and writes more
data into it, that data will be available to the SECOND job that opens that
core link for input. Thus if one job is in a loop opening the core link
named FOO;BAR BAZ, outputting a single character, and then closing it
again, and a second job is in a loop opening that core link, reading
characters until end of file, and then closing it again, then the second
job will see a sequence of single character length files.
We haven't yet mentioned the CLI and CLA devices. These two devices enable
one job to interrupt another job indicating that it wishes to send a
message through a core link. This is how interactive messages work on ITS.
The sending job opens the CLI device with first and second filenames equal
to the UNAME and JNAME of the job that it wishes to interrupt. For
example, a job might try to open CLI:CSTACY HACTRN (any SNAME supplied will
be ignored). ITS then checks to see that a job named CSTACY HACTRN really
does exist. If it does, ITS checks to see that that job has enabled the
%PICLI interrupt. If it is not the case that both conditions are met, the
open returns an illegal file name error (%EBDFN). If both conditions are
met, then we proceed as if we were opening CLO:_CLI_;CSTACY HACTRN. If
that succeeds, then we actually give the job CSTACY HACTRN the %PICLI
interrupt, and the open succeeds.
The UNAME and JNAME of the sending job are now placed in the core link's
I/O buffer so that the receiving job will be able to read them out before
any additional data that the sender might wish to transmit. (Note that you
can only open the CLI device for output.)
In order to handle the %PICLI interrupt the job CSTACY HACTRN opens CLA:
(any additional names supplied will be ignored). This is like opening
CLU:_CLI_;CSTACY HACTRN, except that it saves the interrupted job from
having to figure out its own name. The receiving job can now read the
UNAME and JNAME of its interrupter by inputting the first two 36-bit words
from the newly opened channel.
The jobs are now talking through an ordinary core link named
_CLI_;CSTACY HACTRN.

108
doc/sysdoc/devdoc.5 Executable file
View File

@@ -0,0 +1,108 @@
SUBTTL I/O DEVICE DISPATCH TABLES
COMMENT |
This page tries to document the ITS I/O device dispatch tables and
dispatch environment. It is not completed yet.
The tables use several different indices, which are:
opnidx - result of device name lookup in DEVTAB
ioidx - result of OPEN; has symbolic values. This is the index
stored in RH of IOCHNM (per-job channel table)
sidx - secondary index from DCHSTB(ioidx)
ridx - secondary index from RSTB(ioidx)
The following system calls are dispatched through these tables.
There are 11 dispatch routines that each device must specify.
The format is "CALL [table name(index-used) -> device-routine]"
Unless otherwise noted, context for all routines has
U/ User index
R/ addr of IOCHNM word for specified channel
and the phrase "all ACs can be used" excludes P and U, of course.
and routines can hang (u.o.n.)
OPEN [DEVADR(opnidx) -> devO]
"opnidx" is looked up from DEVTAB which holds the device names.
The device's OPEN routine is in the RH of DEVADR.
It must set up the user's IOCHNM word for the channel,
by setting the RH to the right "ioidx" and the LH to whatever
the device wants.
Context:
A/ FN1
B/ FN2
C/ <mode bits>,,<device name>
D/ <mode bits rotated -1>
E/ <device name>
TT/ DEVADR word <bits>,,<routine>
W/ "open" command (0= Normal R/W open, 1= Write-over mode,
2= Make link, 4= Delete or rename)
SRN3(U),SRN4(U),SRN5(U) - args 4,5,6 (if present)
Routine is JRST'd to, and must return via POPJ1 for success.
Errors should JRST to the appropriate OPNLnn label.
All ACs can be smashed.
CLOSE [CLSTB(ioidx) -> devCLS]
The device's CLOSE routine is in the RH of CLSTB.
Context:
A/ 0,,<LH of IOCHNM word>
B/ 0,,<RH of IOCHNM word>
C/ CLSTB entry, <bits>,,<rtn addr>
R/ addr of IOCHNM word
Called via PUSHJ, must return via POPJ (IOCHNM and IOCHST will
be cleared immediately after return).
Can smash all ACs including R.
Must NOT hang!
IOT, SIOT [IOTTB(ioidx) -> devVarious]
These routines do I/O transfers. The main reason "ioidx"
has so many possible values (causing IOTTB to be large) is
because lots of devices specify different ioidx's for different
modes - input/output, block/unit, image/ascii, etc - in order
to speed up actual I/O transfers, which are probably the most
common device-related system calls.
Context:
Boy is this complicated.
STATUS [LH(DSTSTB(sidx)) -> devSTA]
Context:
R/ addr of IOCHNM word
Called by PUSHJ, must return by POPJ
Must return in RH(D) some device-dependent status stuff.
Calling routine (NSTATUS) fills in the LH from IOCHST.
Must not smash C,R! Probably should not smash other
stuff either, depending on what USRVAR/USET need.
WHYINT [RH(DSTSTB(sidx)) -> devWHY]
RCHST, RFNAME [LH(DRFNTB(sidx)) -> devRCH]
RFPNTR [RH(DRFNTB(sidx)) -> devRFP]
IOPUSH, IOPOP [LH(RSTB1(ridx)) -> devIOP]
RESET [RH(RSTB1(ridx)) -> devRST]
Context:
R/ addr of IOCHNM wd
Called by JRST from NRESET/ARESET/AIOPP1, must return by POPJ.
Can clobber all ACs. Must not hang.
FORCE [LH(DFRCTB(ridx)) -> devFRC]
Context:
A/ LH of IOCHNM word, in RH.
H/ IOCHNM word
R/ <LH of CLSTB entry>,,<addr of IOCHNM word>
Called by JRST from NFORCE. Returns by POPJ1 for win,
POPJ if fail. Should not clobber context that FINISH routine
may need.
FINISH [RH(DFRCTB(ridx)) -> devFIN]
Same as FORCE, except that FORCE is called first, thus
context is whatever FORCE leaves behind. This routine
must do the actual waiting for FORCE's actions to be
finished.
|

638
doc/sysdoc/grphcs.21 Executable file
View File

@@ -0,0 +1,638 @@
This file was moved to MIT-MC from
MIT-AI by David C. Plummer on 6 June
1981, and may be up to date.
NWG/RFC# 746 RMS 17-MAR-78 43976
SUPDUP Graphics Extension
Network Working Group Richard Stallman
Request for Comments 746 MIT-AI
NIC 43976 17 March 1978
The SUPDUP Graphics Extension
... extends SUPDUP to permit the display of drawings on the
screen of the terminal, as well as text. We refer constantly to the
documentation of the SUPDUP protocol, described by Crispin in RFC 734
"SUPDUP Protocol".
Since this extension has never been implemented, it presumably
has some problems. It is being published to ask for suggestions, and
to encourage someone to try to bring it up.
The major accomplishments are these:
* It is easy to do simple things.
* Any program on the server host can at any time begin
outputting pictures. No special preparations are needed.
* No additional network connections are needed. Graphics
commands go through the normal text output connection.
* It has nothing really to do with the network. It is suitable
for use with locally connected intelligent display terminals
in a terminal-independent manner, by programs which need not
know whether they are being used locally or remotely. It can be
used as the universal means of expression of graphics output, for
whatever destination. Programs can be written to use it for
non-network terminals, with little loss of convenience, and
automatically be usable over the ARPA network.
* Loss of output (due, perhaps, to a "silence" command typed
by the user) does not leave the user host confused.
* The terminal does not need to be able to remember the
internal "semantic" structure of the picture being
displayed, but just the lines and points, or even just bits
in a bit matrix.
* The server host need not be able to invoke arbitrary
terminal-dependent software to convert a standard language
into one that a terminal can use. Instead, a standard
language is defined which all programmable terminals can
interpret easily. Major differences between terminals are
catered to by conventions for including enough redundant
information in the output stream that all types of terminals
will have the necessary information available when it is
needed, even if they are not able to remember it in usable
form from one command to another.
Those interested in network graphics should read about the
Multics Graphics System, whose fundamental purpose is the same, but
whose particular assumptions are very different (although it did
inspire a few of the features of this proposal).
NWG/RFC# 746 RMS 17-MAR-78 43976
SUPDUP Graphics Extension
SUPDUP Initial Negotiation:
One new optional variable, the SMARTS variable, is defined. It
should follow the other variables sent by the SUPDUP user process to
the SUPDUP server process. Bits and fields in the left half-word of
this variable are given names starting with "%TQ". Bits and fields in
the right half are given names starting with "%TR". Not all of the
SMARTS variable has to do with the graphics protocol, but most of it
does. The %TQGRF bit should be 1 if the terminal supports graphics
output at all.
Invoking the Graphics Protocol:
Graphics mode is entered by a %TDGRF (octal 231) code in the
output stream. Following characters in the range 0 - 177 are
interpreted according to the graphics protocol. Any character 200 or
larger (a %TD code) leaves graphics mode, and then has its normal
interpretation. Thus, if the server forgets that the terminal in
graphics mode, the terminal will not long remain confused.
Once in graphics mode, the output stream should contain a
sequence of graphics protocol commands, each followed by its
arguments. A zero as a command is a no-op. To leave graphics mode
deliberately, it is best to use a %TDNOP.
NWG/RFC# 746 RMS 17-MAR-78 43976
SUPDUP Graphics Extension
Co-ordinates:
Graphics mode uses a cursor position which is remembered from one
graphics command to the next while in graphics mode. The graphics
mode cursor is not the same one used by normal type-out: Graphics
protocol commands have no effect on the normal type-out cursor, and
normal type-out has no effect on the graphics mode cursor. In
addition, the graphics cursor's position is measured in dots rather
than in characters. The relationship between the two units (dots, and
characters) is recorded by the %TQHGT and %TQWID fields of the SMARTS
variable of the terminal, which contain the height and width in dots
of the box occupied by a character. The size of the screen in either
dimension is assumed to be the length of a character box times the
number of characters in that direction on the screen. If the screen
is actually bigger than that, the excess may or may not be part of
the visible area; the program will not know that it exists, in any
case.
Each co-ordinate of the cursor position is a 14-bit signed
number, where zero is at the center of the screen (if the screen
dimension is an even number of dots, then the visible negative points
extend one unit farther than the positive ones, in proper two's
complement fashion). Excessively large values of the co-ordinates
will be off the screen, but are still meaningful.
An alternate mode is defined, which some terminals may support,
in which virtual co-ordinates are used. The specified co-ordinates
are still 14-bit signed numbers, but instead of being in units of
physical dots on the terminal, it is assumed that +4000 octal is the
top of the screen or the right edge, while -4000 octal is the bottom
of the screen or the left edge. The terminal is responsible for
scaling these virtual co-ordinates into units of screen dots. Not all
terminals need have this capability; the %TQVIR bit in the SMARTS
variable indicates that it exists. To use virtual co-ordinates, the
server should send a %GOVIR; to use physical co-ordinates again, it
should send a %GOPHY. These should be repeated at intervals, such as
when graphics mode is entered, even though the terminal must attempt
to remember the state of the switch anyway. This repetition is so
that a loss of some output will not cause unbounded confusion.
The virtual co-ordinates are based on a square. If the visible
area on the terminal is not a square, then the standard virtual range
should correspond to a square around the center of the screen, and the
rest of the visible area should correspond to virtual co-ordinates
just beyond the normally visible range.
Graphics protocol commands take two types of cursor position
arguments, absolute ones and relative ones. Commands that take
address arguments generally have two forms, one for each type of
address. A relative address consists of two offsets, delta-X and
delta-Y, from the old cursor position. Each offset is a 7-bit two's
complement number occupying one character. An absolute address
consists of two co-ordinates, each 14 bits long, occupying two
characters, each of which conveys 7 bits. The X co-ordinate or offset
precedes the Y. Both types of address set the running cursor position
which will be used by the next address, if it is relative. It is
perfectly legitimate for parts of objects to go off the screen. What
happens to them is not terribly important, as long as it is not
disastrous, does not interfere with the reckoning of the cursor
position, and does not cause later objects, drawn after the cursor
moves back onto the screen, to be misdrawn.
Whether a particular spot on the screen is specified with an
absolute or a relative address is of no consequence. The sequence in
which they are drawn is of no consequence. Each object is independent
of all others, and exists at the place which was specified, in one way
or other, by the command that created it. Relative addresses are
provided for the sake of data compression. They are not an attempt to
spare programs the need for the meagre intelligence required to
convert between absolute and relative addresses; more intelligence
than that will surely be required for other aspects of the graphics
protocol. Nor are relative addresses intended to cause several
objects to relocate together if one is "moved" or erased. Terminals
are not expected to remember any relation between objects once they
are drawn. Most will not be able to.
Although the cursor position on entry to graphics mode remains
set from the last exit, it is wise to reinitialize it with a %GOMVA
command before any long transfer, to limit the effects of lost output.
NWG/RFC# 746 RMS 17-MAR-78 43976
SUPDUP Graphics Extension
Commands:
Commands to draw an object always have counterparts which erase
the same object. On a bit matrix terminal, erasure and drawing are
almost identical operations. On a display list terminal, erasure
involves searching the display list for an object with the specified
characteristics and deleting it from the list. Thus, on such
terminals you can erase an object only if precisely that object was
drawn, and was specified the same way when drawn as when erased.
(presumably; a very hairy program might allow more). Any terminal
whose %TOERS bit is set must be able to erase to at least that extent.
The commands to draw objects run from 100 to 137, while those to
erase run in a parallel sequence from 140 to 177. Other sorts of
operations have command codes below 100. Meanwhile, the 20 bit in the
command code says which type of addresses are used as arguments: if
the 20 bit is set, absolute addresses are used. Graphics commands are
given names starting with "%GO".
Graphics often uses characters. The %GODCH command is followed
by a string of characters to be output, terminated by a zero. The
characters must be single-position printing characters. On most
terminals, this limits them to ASCII graphic characters. Terminals
with %TOSAI set in the TTYOPT variable allow all characters 0-177.
The characters are output at the current graphics cursor position (the
lower left hand corner of the first character's rectangle being placed
there), which is moved as the characters are drawn. The normal
type-out cursor is not relevant and its position is not changed. The
cursor position at which the characters are drawn may be in between
the lines and columns used for normal type-out. The %GOECH command is
similar to %GODCH but erases the characters specified in it. To clear
out a row of character positions on a bit matrix terminal without
having to respecify the text, a rectangle command may be used.
Example:
The way to send a simple line drawing is this:
%TDRST ;Reset all graphics modes.
%TDGRF ;Enter graphics.
%GOCLR ;Clear the screen.
%GOMVA xx yy ;Set cursor.
%GODLA xx yy ;Draw line from there.
<< repeat last two commands for each line >>
%TDNOP ;Exit graphics.
NWG/RFC# 746 RMS 17-MAR-78 43976
SUPDUP Graphics Extension
Graphics Input:
The %TRGIN bit in the right half of the SMARTS variable indicates
that the terminal can supply a graphic input in the form of a cursor
position on request. Sending a %GOGIN command to the terminal asks to
read the cursor position. It should be followed by an argument
character that will be included in the reply, and serve to associate
the reply with the particular request for input that elicited it. The
reply should have the form of a Top-Y character (code 4131), followed
by the reply code character as just described, followed by an absolute
cursor position. Since Top-Y is not normally meaningful as input,
%GOGIN replies can be distinguished reliably from keyboard input.
Unsolicited graphic input should be sent using a Top-X instead of a
Top-Y, so that the program can distinguish them. Instead of a reply
code, for which there is no need, the terminal should send an encoding
of the buttons pressed by the user on his input device, if it has more
than one.
Sets:
Terminals may define the concept of a "set" of objects. There
are up to 200 different sets, each of which can contain arbitrarily
many objects. At any time, one set is selected; objects drawn become
part of that set, and objects erased are removed from it. Objects in
a set other than the selected one cannot be erased without switching
to the sets that contain them. A set can be made temporarily
invisible, as a whole, without being erased or its contents forgotten;
and it can then be made instantly visible again. Also, a whole set
can be moved. A set has at all times a point identified as its
"center", and all objects in it are actually remembered relative to
that center, which can be moved arbitrarily, thus moving all the
objects in the set at once. Before beginning to use a set, therefore,
one should "move" its center to some absolute location. Set center
motion can easily cause objects in the set to move off screen. When
this happens, it does not matter what happens temporarily to those
objects, but their "positions" must not be forgotten, so that undoing
the set center motion will restore them to visibility in their
previous positions. Sets are not easily implemented on bit matrix
terminals, which should therefore ignore all set operations (except,
for a degenerate interpretation in connection with blinking, if that
is implemented). The %TQSET bit in the SMARTS variable of the
terminal indicates that the terminal implements multiple sets of
objects.
On a terminal which supports multiple sets, the %GOCLR command
should empty all sets and mark all sets "visible" (perform a %GOVIS on
each one). So should a %TDCLR SUPDUP command. Thus, any program
which starts by clearing the screen will not have to worry about
initializing the states of all sets.
NWG/RFC# 746 RMS 17-MAR-78 43976
SUPDUP Graphics Extension
Blinking:
Some terminals have the ability to blink objects on the screen.
The command %GOBNK meaning make the current set blink. All objects in
it already begin blinking, and any new objects also blink. %GOVIS or
%TOINV cancels the effect of a %GOBNK, making the objects of the set
permanently visible or invisible. %TQBNK indicates that the terminal
supports blinking on the screen.
However, there is a problem: some intelligent bit matrix
terminals may be able to implement blinking a few objects, if they are
told in advance, before the objects are drawn. They will be unable to
support arbitrary use of %GOBNK, however.
The solution to the problem is a convention for the use of %TOBNK
which, together with degenerate definitions for set operations, makes
it possible to give commands which reliably work on any terminal which
supports blinking.
On a terminal which sets %TQBNK but not %TQSET, %GOBNK is defined
to cause objects which are drawn after it to be drawn blinking.
%GOSET cancels this, so following objects will be drawn unblinking.
This is regardless of the argument to the %GOSET.
Thus, the way for a program to work on all terminals with %TQBNK,
whether they know about sets or not, is: to write a bliniking
picture, select some set other than your normal one (set 1 will do),
do %GOBNK, output the picture, and reselect set 0. The picture will
blink, while you draw things in set 0. To draw more blinking objects,
you must reselect set 1 and do another %GOBNK. Simply reselecting set
1 will not work on terminals which don't really support sets, since
they don't remember that the blinking objects are "in set 1" and not
"in set 0".
Erasing a blinking object should make it disappear, on any
terminal which implements blinking. On bit matrix terminals, blinking
MUST always be done by XORing, so that the non-blinking background
is not destroyed.
%GOCLS, on a terminal which supports blinking but not sets,
should delete all blinking objects. Then, the convention for deleting
all blinking objects is to select set 1, do a %GOCLS, and reselect set
0. This has the desired effect on all terminals. This definition of
%GOCLS causes no trouble on non-set terminals, since %GOCLS would
otherwise be meaningless to them.
To make blinking objects stop blinking but remain visible is
possible with a %GOVIS on a terminal which supports sets. But in
general the only way to do it is to delete them and redraw them as
permanent.
NWG/RFC# 746 RMS 17-MAR-78 43976
SUPDUP Graphics Extension
Rectangles and XOR Mode:
Bit matrix terminals have their own operations that display list
terminals cannot duplicate. First of all, they have XOR mode, in
which objects drawn cancel existing objects when they overlap. In
this mode, drawing an object and erasing it are identical operations.
All %GOD.. commands act IDENTICALLY to the corresponding %GOE..'s.
XOR mode is entered with a %GOXOR and left with a %GOIOR. Display
list terminals will ignore both commands. For that reason, the
program should continue to distinguish draw commands from erase
commands even in XOR mode. %TQXOR indicates a terminal which
implements XOR mode. XOR mode, when set, remains set even if graphics
mode is left and re-entered. However, it is wise to re-specify it
from time to time, in case output is lost.
Bit matrix terminals can also draw solid rectangles. They can
thus implement the commands %GODRR, %GODRA, %GOERR, and %GOERA. A
rectangle is specified by taking the current cursor position to be one
corner, and providing the address of the opposite corner. That can be
done with either a relative address or an absolute one. The %TQREC
bit indicates that the terminal implements rectangle commands.
Of course, a sufficiently intelligent bit matrix terminal can
provide all the features of a display list terminal by remembering
display lists which are redundant with the bit matrix, and using them
to update the matrix when a %GOMSR or %GOVIS is done. However, most
bit matrix terminals are not expected to go to such lengths.
NWG/RFC# 746 RMS 17-MAR-78 43976
SUPDUP Graphics Extension
How Several Process Can Draw On One Terminal Without Interfering With
Each Other:
If we define "input-stream state" information to be whatever
information which can affect the action of any command, other than
what is contained in the command, then each of the several processes
must have its own set of input-stream state variables.
This is accomplished by providing the %GOPSH command. The %GOPSH
command saves all such input-stream information, to be restored when
graphics mode is exited. If the processes can arrange to output
blocks of characters uninterruptibly, they can begin each block with a
%GOPSH followed by commands to initialize the input-stream state
information as they desire. Each block of graphics output should be
ended by a %TDNOP, leaving the terminal in its "normal" state for all
the other processes, and at the same time popping the what the %GOPSH
pushed.
The input-stream state information consists of:
The cursor position
the state of XOR mode (default is OFF)
the selected set (default is 0)
the co-ordinate unit in use (physical dots, or virtual)
(default is physical)
whether output is going to the display screen or to a hardcopy
device (default is to the screen)
what portion of the screen is in use
(see "Using Only Part of the Screen")
(default is all)
Each unit of input-stream status has a default value for the sake
of programs that do not know that the information exists; the
exception is the cursor position, since all programs must know that it
exists. A %TDINI or %TDRST command should set all of the variables to
their default values.
The state of the current set (whether it is visible, and where
its center is) is not part of the input-stream state information,
since it would be hard to say what it would mean if it were. Besides,
the current set number is part of the input-stream state information,
so different processes can use different sets. The allocation of sets
to processes is the server host's own business.
NWG/RFC# 746 RMS 17-MAR-78 43976
SUPDUP Graphics Extension
Using Only Part of the Screen:
It is sometimes desirable to use part of the screen for picture
and part for text. Then one may wish to clear the picture without
clearing the text. On display list terminals, %GOCLR should do this.
On bit matrix terminals, however, %GOCLR can't tell which bits were
set by graphics and which by text display. For their sake, the %GOLMT
command is provided. This command takes two cursor positions as
arguments, specifying a rectangle. It declares that graphics will be
limited to that rectangle, so %GOCLR should clear only that part of
the screen. %GOLMT need not do anything on a terminal which can
remember graphics output as distinct from text output and clear the
former selectively, although it would be a desirable feature to
process it even on those terminals.
%GOLMT can be used to enable one of several processes which
divide up the screen among themselves to clear only the picture that
it has drawn, on a bit matrix terminal. By using both %GOLMT and
distinct sets, it is possible to deal successfully with almost any
terminal, since bit matrix terminals will implement %GOLMT and display
list terminals almost always implement sets.
The %TDCLR command should clear the whole screen, including
graphics output, ignoring %GOLMT.
Errors:
In general, errors in graphics commands should be ignored.
Since the output and input streams are not synchronized unless
trouble is taken, there is no simple way to report an error well
enough for the program that caused it to identify just which command
was invalid. So it is better not to try.
Errors which are not the fault of any individual command, such as
running out of memory for display lists, should also be ignored as
much as possible. This does NOT mean completely ignoring the commands
that cannot be followed; it means following them as much as possible:
moving the cursor, selecting sets, etc. as they specify, so that any
subsequent commands which can be executed are executed as intended.
NWG/RFC# 746 RMS 17-MAR-78 43976
SUPDUP Graphics Extension
Extensions:
This protocol does not attempt to specify commands for dealing
with every imaginable feature which a picture-drawing device can have.
Additional features should be left until they are needed and well
understood, so that they can be done right.
Storage of Graphics Commands in Files:
This can certainly be done. Since graphics commands are composed
exclusively of the ASCII characters 0 - 177, any file that can hold
ASCII text can hold the commands to draw a picture. This is less
useful than you might think, however. Any program for editing, in
whatever loose sense, a picture, will have its own internal data which
determine the relationships between the objects depicted, and control
the interpretation of the programs commands, and this data will all be
lost in the SUPDUP graphics commands for displaying the picture.
Thus, each such program will need to have its own format for storing
pictures in files, suitable for that program's internal data
structure. Inclusion of actual graphics commands in a file will be
useful only when the sole purpose of the file is to be displayed.
NWG/RFC# 746 RMS 17-MAR-78 43976
SUPDUP Graphics Extension
Note: the values of these commands are represented as 8.-bit octal
bytes. Arguments to the commands are in lower case inside angle
brackets.
The Draw commands are:
Value Name Arguments
101 %GODLR <p>
Draw line relative, from the cursor to <p>.
102 %GODPR <p>
Draw point relative, at <p>.
103 %GODRR <p>
Draw rectangle relative, corners at <p> and at the
current cursor position.
104 %GODCH <string> <0>
Display the chars of <string> starting at the current
graphics cursor position.
121 %GODLA <p>
Draw line absolute, from the cursor to <p>.
The same effect as %GODLR, but the arg is an absolute
address.
122 %GODPA <p>
Draw point absolute, at <p>.
123 %GODRA <p>
Draw rectangle absolute, corners at <p> and at the
current cursor position.
The Erase commands are:
Value Name Arguments
141 %GOELR <p>
Erase line relative, from the cursor to <p>.
142 %GOEPR <p>
Erase point relative, at <p>.
143 %GOERR <p>
Erase rectangle relative, corners at <p> and at the
current cursor position.
144 %GOECH <string> <0>
Erase the chars of <string> starting at the current
graphics cursor position.
161 %GOELA <p>
Erase line absolute, from the cursor to <p>.
162 %GOEPA <p>
Erase point absolute, at <p>.
163 %GOERA <p>
Erase rectangle absolute, corners at <p> and at the
current cursor position.
NWG/RFC# 746 RMS 17-MAR-78 43976
SUPDUP Graphics Extension
The miscellaneous commands are:
Value Name Arguments
001 %GOMVR <p>
Move cursor to point <p>
021 %GOMVA <p>
Move cursor to point <p>, absolute address.
002 %GOXOR
Turn on XOR mode. Bit matrix terminals only.
022 %GOIOR
Turn off XOR mode.
003 %GOSET <n>
Select set. <n> is a 1-character set number, 0 - 177.
004 %GOMSR <p>
Move set origin to <p>. Display list terminals only.
024 %GOMSA <p>
Move set origin to <p>, absolute address.
006 %GOINV
Make current set invisible.
026 %GOVIS
Make current set visible.
007 %GOBNK
Make current set blink. Canceled by %GOINV or %GOVIS.
010 %GOCLR
Erase whole screen.
030 %GOCLS
Erase entire current set (display list terminals).
011 %GOPSH
Push all input-stream status information, to be
restored when graphics mode is exited.
012 %GOVIR
Start using virtual co-ordinates
032 %GOPHY
Resume giving co-ordinates in units of dots.
013 %GOHRD <n>
Divert output to output subdevice <n>.
<n>=0 reselects the main display screen.
014 %GOGIN <n>
Request graphics input (mouse, tablet, etc).
<n> is the reply code to include in the answer.
015 %GOLMT <p1> <p2>
Limits graphics to a subrectangle of the screen.
%GOCLR will clear only that area. This is for those
who would use the rest for text.
NWG/RFC# 746 RMS 17-MAR-78 43976
SUPDUP Graphics Extension
Bits in the SMARTS Variable Related to Graphics:
Note: the values of these bits are represented as octal 36.-bit words,
with the left and right 18.-bit halfword separated by two commas as in
the normal PDP-10 convention.
Name Value Description
%TQGRF 000001,,0 terminal understands graphics protocol.
%TQSET 000002,,0 terminal supports multiple sets.
%TQREC 000004,,0 terminal implements rectangle commands.
%TQXOR 000010,,0 terminal implements XOR mode.
%TQBNK 000020,,0 terminal implements blinking.
%TQVIR 000040,,0 terminal implements virtual co-ordinates.
%TQWID 001700,,0 character width, in dots.
%TQHGT 076000,,0 character height, in dots.
%TRGIN 0,,400000 terminal can provide graphics input.
%TRGHC 0,,200000 terminal has a hard-copy device to which output
can be diverted.
;;;Local Modes:
;;;Mode:Text
;;;Auto Fill Mode:1
;;;Fill Column:70
;;;End:

562
doc/sysdoc/intrup.108 Executable file
View File

@@ -0,0 +1,562 @@
Overview of ITS User Interrupts
When ITS wishes to signal a user program of the existence of an
unusual interesting condition or occurrence, it does so via
the "user interrupt" mechanism. This mechanism essentially
causes the user program to call an interrupt handling subroutine
in the middle of what it had been doing. The interrupt handler has
enough information to be able to return to the interrupted code
without any effects on it if desired, and to determine the cause
of the interrupt so as to take appropriate action. The program
can specify which interrupt conditions it wishes to handle, and
what their priority order should be; un-handled interrupts are
either ignored or fatal depending on the condition. Some interrupt
conditions represent errors in the execution of the job; some
indicate the occurrence of asynchronous events such as I/O operation
completion; some exist for debugging and are always fatal.
The noun "interrupt" may mean either the event of interrupting
a program (causing it to call the handler), or a condition which
can cause a program to be interrupted. Also, the distinction
between an interrupt condition and the bit which is 1 when the
condition is present is often blurred.
Unlike TENEX, ITS never gives the user an interrupt "in the middle
of a system call". The PC saved by an interrupt is always a user-mode PC.
This is a great advantage when it comes to having the interrupt handler
understand what the interrupted code was doing and fix it up.
System calls will either be finished or backed out of (to be redone)
when it is necessary for the job to be interrupted. To avoid having to
do a lot of work twice, all ITS system calls that take a long time to
complete are designed so that if restarted they will continue from
where they left off. They do this by updating their arguments to
indicate how much progress they have made, just like the BLT instruction.
Now you know why SIOT and block-mode IOT update their pointer and
byte count as they go.
Section A describes how interrupts are signaled and enabled, etc.
Section B describes what is actually done to a job when it is
interrupted, if it uses the older simple interrupt mechanism.
Section C gives an example of an old-style interrupt handler.
Section D describes what is actually done to a job when it is
interrupted, if it uses the newer vectored interrupt mechanism.
Section E describes the individual interrupt conditions in the
first interrupt request word (.PIRQC).
Section F describes the individual interrupt conditions in the
second interrupt request word (.IFPIR).
A. The ITS Interrupt Mechanism
Each ITS job has two "interrupt request words", called .PIRQC
and .IFPIR, and readable with .SUSET. Each distinct interrupt
condition is assigned one of the bits in one of the words.
The interrupt is "pending" when the bit is 1.
.PIRQC is called the "first interrupt word" and interrupts in it
are "first word interrupts". .IFPIR is the "second interrupt word"
and its interrupts are "second word interrupts".
Interrupt conditions are divided by the system into three severity classes.
Class 1 interrupts are always fatal. They are genarally conditions caused
by the user or the superior, for debugging purposes; for example,
breakpoints, ^Z typed, and single-instruction-proceed interrupts are
of class 1. Class 2 interrupts are fatal unless the program is set up
to handle the interrupt. Most error conditions are class 2; for example,
MPV (memory protect violation), ILOPR (illegal operation), IOCERR
(I/O channel error). All class 1 and 2 interrupts are first word
interrupts. Class 3 interrupts are never fatal unless the user
explicitly makes them so; either the program is eventually interrupted
or nothing happens. Most asynchronous conditions are class 3.
When a job receives a fatal interrupt, that job is not interrupted
itself; instead, it is stopped, as if its superior had stopped it,
and an "inferior got a fatal interrupt" interrupt is signaled for the
superior. If a top level job receives a fatal interrupt, then it will
be stopped and detached (see the symbolic system call DETACH).
Each interrupt word has a corresponding mask word: .MASK for .PIRQC,
and .MSK2 for .IFPIR. An interrupt is enabled if the appropriate bit in
the mask word is 1. A program will not receive an interrupt which is
disabled, but if the interrupt condition is in class 2 it
will be fatal if it is not enabled. Class 3 interrupts will not even
be signaled if they are disabled. Class 1 interrupts are not allowed
to be enabled, the idea being that the job which gets an always-fatal
interrupt is not allowed to handle the interrupt itself.
Each interrupt word also has a defer word: .DF1 for .PIRQC, and
.DF2 for .IFPIR. If the appropriate bit in the defer word is set,
the interrupt is "deferred". For a class 2 interrupt, deferment has
the same effect as disablement: the interrupt becomes fatal.
For a class 1 interrupt, deferment has no effect. For a class 3
interrupt, deferment differs from disablement in that a deferred
interrupt will still be signaled; it will then remain pending until
it is no longer deferred, when it will be given to the user.
The system makes it easy to defer a specified set of interrupts while
processing an interrupt. That is how different priorities of
interrupts may exist.
Slightly obsolete but still useful is the variable .PICLR, which is
normally -1. If this variable is set to 0, all interrupts are deferred.
The actual values of the defer words are unaltered. .PICLR was
the original way to defer interrupts, before the defer words existed.
The older style of interrupt handling on ITS sets .PICLR to 0 while
an interrupt is being processed; thus, there is only one interrupt
priority level.
To help eliminate timing errors, the six variables .PIRQC, .IFPIR,
.MASK, .MSK2, .DF1 and .DF2 have aliases which have the same value
when read, but when written either IORM or ANDCAM into the variable
instead of setting all the bits in it. These aliases are called
.IPIRQC, .IIFPIR, .IMASK, .IMSK2, .IDF1 and .IDF2 for IORM'ing,
and .APIRQC, .AIFPIR, .AMASK, .AMSK2, .ADF1 and .ADF2 for ANDCAM'ing.
Thus, depositing 20 in .APIRQC will clear the 20 bit in .PIRQC.
Error-condition interrupts (MPV, ILOPR, IOCERR, WIRO, DTTY and some others)
usually abort the instruction that causes them. When this happens,
the old convention (still the default) is to leave the PC pointing
AFTER the aborted instruction. This is very bad since it is hard
for the user's interrupt handler to tell whether to decrement the PC.
The new convention, selected by setting bit %OPOPC in the LH of the
.OPTION variable to 1, is for the system to decrement the PC when
a fatal interrupt happens, so that if the interrupt handler fixes
the problem (e.g. creates the nonexistent page of core) and dismisses,
the instruction will be retried. All new programs should use the
new convention; it would be nice to flush the old one entirely.
B. How Jobs Are Informed about Their Interrupts (Old Style)
There are two ways for a program to receive interrupts from the
system: the old way, and the new way. The old scheme always stores
the PC in the same place, making recursive interrupts difficult.
It also makes all interrupts have the same priority level.
The new scheme pushes the interrupt information on a stack. It also
has the ability to decode the interrupts for the user, whereas with the
old mechanism the program must decode the interrupts. Nevertheless,
the old mechanism is not considered obsolete, since it is easier to use.
Both mechanisms have the user's interrupt handler information pointed
to by location 42. More generally, the address of the interrupt pointer
is 2 plus the rh of the .40ADDR variable; since .40ADDR usually holds
40, the interrupt pointer usually lives in 42.
The two mechanisms are selected by the %OPINT bit of the .OPTION
variable: the new mode is used if the bit is 1.
In the old mode, 42 is expected to contain the address of the
interrupt handler itself. Let that address be called "TSINT"
(every program should use that label, for the sake of humans).
If TSINT is 0, or addresses nonexistent or pure storage,
when the system attempts to interrupt the job, an always-fatal
BADPI (%PIB42) interrupt is signaled and the program does not
receive the original interrupts. If the superior, handling the BADPI,
fixes up 42 and restarts the job, it will then be properly interrupted.
When an interrupt happens, all the
pending enabled undeferred first word interrupts will be given to
the user at once if there are any; otherwise, all the pending
enabled undeferred second word interrupts will be given. The
interrupts which are given will be cleared in the request word.
Whichever interrupt request word is being given will be stored in TSINT.
If the interrupts being handled are second-word interrupts, the sign
of TSINT will be set. The PC is stored in TSINT+1. The job is then
started at TSINT+2, with all PC flags except user and user-i/o zeroed.
The job's .PICLR will be set to 0, preventing further interrupts while
the interrupt handler is running. Because more than one interrupt
may be given to the user at once, the interrupt routine should check
all of the interrupt bits, and after handling one interrupt should
return to check the remaining bits.
The normal way for the interrupt handler
to exit is with the .DISMIS uuo, which should address a word containing
the desired new PC. .DISMIS jumps to that PC, restoring flags, and also
sets .PICLR to -1 to allow interrupts again. To restart the program
where it was interrupted, .DISMIS TSINT+1 should be used. The program
may desire to restore the saved PC flags but a different PC; in that
case, it should probably clear the byte-interrupt flag (%PCFPD) before
restoring the flags.
C. An Example of an Old Style Interrupt Handler
TSINT:
LOC 42
TSINT ;this is the interrupt pointer. -> int handler.
LOC TSINT
0 ;first word of handler gets the bits for the interrupts
0 ;second gets the PC
EXCH A,TSINT
JUMPL A,TSINT2 ;sign of int word set => second word interrupts;
TLNE A,%PJRLT ;otherwise, they are first word interrupts.
PUSHJ P,TIMINT ;if we got an alarm clock int, handle that.
TRNE A,%PIMPV
PUSHJ P,MPVINT ;if we got an MPV, handle that.
TRNE A,%PIIOC
PUSHJ P,IOCINT ;if we got an IOCERR, handle that.
TSINTX: EXCH A,TSINT
.DISMIS TSINT+1 ;then restore the saved PC and zero .PICLR.
TSINT2: TRNE A,1_TYIC
PUSHJ P,INPUTI ;handle characters typed on the tty (assuming
;that tty input is open on channel TYIC)
TDNE A,INFBIT
PUSHJ P,INFINT ;handle interrupts from one of our inferiors,
;assuming the inferior's .INTB variable was
;read into INFBIT.
JRST TSINTX
;if the program can't recover from MPV's well, it might do this:
MPVINT: <TYPE ERROR MESSAGE SOMEHOW>
.DISMIS [RESTART] ;re-initialize the program.
;if it wanted to create the referenced page, it might do this:
MPVINT: PUSH P,B
.SUSET [.RMPVA,,B]
LSH B,-10. ;get the referenced page's number.
.CALL [ SETZ ? 'CORBLK
MOVEI 400000 ? MOVEI -1 ? B ? SETZI 400001]
.VALUE ; ^ get a fresh page into page w/ number in B.
POP P,B
POPJ P,
D. How Jobs Are Informed about Their Interrupts (New Style)
When using the newer interrupt mechanism, the program must divide
the interrupts that it handles into some number of groups (there
may be as few as one interrupt in a group, or all the interrupts
may be in one group). The interrupts in a group are all handled
the same way; they have the same relative priority to all other
interrupts, and have the same handler address. For each group,
the user must specify to the system which interrupts are in it,
which interrupts are considered to have a lower priority than
those in the group, and where the handler for the group is located.
This is done with the "interrupt table", which should be 5n+1 words
long where n is the number of groups. The interrupt table should
be identified to the system by means of an AOBJN pointer in 42.
The first word of the interrupt table should hold the address
of the interrupt stack (which may be an accumulator - P will work!).
The LH of this word specifies extra information to be pushed on
the interrupt stack at each interrupt, beyond the necessary minimum:
bits 3.5-3.1 # of ACs to push. 0 => don't push any ACs.
bits 3.7-4.1 # of first AC to push.
bit 4.9 1 => push the .JPC and .SUUOH variables, and the LSPCL
(an internal ITS variable), after the ACs if any.
Then come five words for each interrupt group. Their meanings are:
wd 1 The 1st word interrupts that are in this group.
If a bit is set in this word, the corresponding interrupt is
in this group.
wd 2 The 2nd word interrupts which are in this group.
wd 3 The 1st word interrupts that are of priority less than or equal to
this group's. Give the bits for the appropriate interrupts.
When interrupts in this group happen, these bits will be
set in .DF1 to prevent the lower-priority interrupts from
happening. Note that it is not obligatory to include the
interrupts of the group itself in this word; if they are not
included, they will be able to interrupt recursively. That is
sometimes desirable for recoverable synchronous conditions.
wd 4 The 2nd word interrupts that are ofthe same or lower priority.
wd 5 The address of the handler for this group.
Note that the priority-relation between interrupts, specified by the
second and third words of the groups in the interrupt table, need not
be even a partial order: it is permissible for interrupt A to defer
only B, B to defer only C, and C to defer only A, although not very
useful. Often, a synchronous interrupt is left incomparable with all
other interrupts - it defers only itself, or nothing.
Synchronous interrupts should come before asynchronous ones
in the table. The only time an exception to that is safe is when
the asynchronous interrupt defers the synchronous one. The reason for
this rule is that when a synchronous interrupt and an asynchronous one
are signalled at the same time, if the asynchronous interrupt comes
earlier in the table it will happen first; if the synchronous one is
not then deferred, it will interrupt saving a PC pointing at the first
word of the asynchronous interrupt's handler - which is not the address
of the instruction that actually caused the synchronous interrupt. If
the synchronous interrupt's handler looks at the PC, as many do, it will
be confused.
This is an example of an interrupt table (taken from DDT).
TSINT: LOC 42
-TSINTL,,TSINT
LOC TSINT
P ;interrupt pdl pointer address.
%PIWRO ? 0 ? 0 ? 0 ? PURBR1
;pure-page violations don't inhibit anything.
;DDT wants to type out ":UNPURE", and doesn't
;like to type out with any interrupts inhibited.
%PITTY ? 0 ? %PITTY ? 0 ? TTYINT
;Don't-have-tty interrupts defer themselves
;so that they become fatal while one is being
;processed. If DDT decides that the one
;that happened should have been fatal, it
;signals another by depositing in .IPIRQC, and
;that one IS fatal since it is deferred.
%PIIOC\%PIILO\%PIMPV\%PIOOB ? 0 ? #%PITTY ? -1 ? TSIN0
;Error interrupts inhibit asynchronous ints for
;safety's sake, and themselves so an error in
;the handler will be fatal.
#%PIIOC#%PIILO#%PIMPV#%PIOOB#%PIWRO#%PICLI#%PITTY ? #<1_TYOC>#1_TYOBC
#%PIIOC#%PIILO#%PIMPV#%PIOOB#%PIWRO#%PICLI#%PITTY ? -1 ? TSIN0
;Miscellaneous interrupts have the same handler
;as the errors - for historical reasons - but
;don't defer the errors, so that DDT can recover
;if an error happens in a miscellaneous int.
0 ? 1_TYOC+1_TYOBC ? 0 ? 0 ? MORINT
;Bottom-of-screen-on-terminal interrupts defer nothing,
;so they can exit by simply jumping if they wish.
%PICLI ? 0 ? %PICLI ? 0 ? CLIBRK
;Core-link interrupts (someone is :SEND'ing to me).
TSINTL==.-TSINT
The algorithm for giving a set of interrupts is:
Look through the interrupt block one group at a time.
If a group is found that applies to any of the interupts that
are to be given, all the interrupts that it applies to and that are
to be given are pushed, together, onto the interrupt stack
at once. The words pushed are:
First, two words containing the interrupts being pushed.
The first word interrupt bits are pushed first.
Next, two words containing the old settings of .DF1 and .DF2.
The old .DF1 is pushed first.
Next, a word containing the PC before the interrupt.
Last, any AC's or debugging variables specified by the LH of
the first word of the interrupt table. These are pushed in the
order: AC's first, then .JPC, then .SUUOH, and finally LSPCL.
If pdl overflow is enabled, it will be detected properly when the
interrupt data is pushed.
After the necessary information has been saved and the interrupt pdl
updated, the defer words and the PC will be set as specified
in the the interrupt table.
At this point, if there still remain any pending enabled undeferred
interrupts, the whole process is repeated, scanning through all the
groups from the beginning. Note that giving one interrupt may cause
other previously undeferred interrupts to be deferred. It may also
set the pdl overflow interrupt, in which case that interrupt will
be given immediately if not deferred.
If there are pending enabled undeferred interrupts not included
in any group, and they do not become deferred by the giving of other
interrupts, then they are considered immediately fatal. Thus, the
user can make a nonfatal interrupt be fatal by enabling it but not
including it in any group.
The interrupt routine may conveniently
exit with the DISMIS Symbolic System Call.
The first arg, if not immediate, should point at the interrupt stack:
.CALL [SETZ ? 'DISMIS ? SETZ P]
The defer words and PC will be restored from the top 3
words on the stack and 5 words will be popped. Stack overflow
will be detected. You may specify that extra things should be popped
using the control bit argument; bit 2.9 specifies that three words
should be discarded, while <m>*100+<n> specifies that ACs <m> through
<m>+<n>-1 should be popped. Thus, it is a win to give, as the control
bit argument (in the RH) whatever was put in the LH of the first word
of the interrupt table - that will cause the DISMIS to pop exactly
what interrupts push.
If the first arg is immediate, clearly nothing can be popped:
.CALL [SETZ ? 'DISMIS ? SETZI 2+[DF1 ? DF2 ? PC] ]
In this case the control-bit argument is ignored.
If a second argument is given, it is used as the new PC
instead of what is found on the interrupt stack.
Similarly, optional third and fourth arguments specify the new
contents of the defer words, overriding what was saved on the stack.
Thus, if four arguments are given and the first is immediate,
the first argument is effectively ignored.
E. The Interrupt Bits in the First Interrupt Word.
The interrupt classes are:
[1] stops job and interrupts superior (fatal intr)
[2] stops job and interrupts superior unless enabled and undeferred
[3] does nothing unless enabled; waits if deferred.
Bits in the lh have two names: %PI... as a bit in the word,
and %PJ... shifted down by 18. bits.
The following interrupts abort the instruction, and leave the PC pointing
before the instruction if %OPOPC is 1 (as is winning), or after it if
%OPOPC is 0: %PIMPV, %PIOOB, %PIIOC, %PIILO, %PJTTY, %PJWRO, %PJFET, %PJTRP.
"(S)" indicates a synchronous interrupt; "(A)", an asynchronous one.
An interrupt is synchronous if its occurrence is always directly related
to the instruction that is being executed when it is signaled.
;RH bits
%PICLI==400000 ;CLI interrupt [3] (A)
;Some job opened the CLI device with filenames equal
;to the uname and jname of this job.
%PIPDL==200000 ;PDL overflow [3] (S)
%PILTP==100000 ;340 or E&S light pen hit [3] (A)
%PIMAR==40000 ;MAR hit. [2] (S)
;The MAR is a hardware feature that allows
;references to a specific memory location to
;be trapped. This is the interrupt that happens
;when such a reference is detected. The guilty
;instuction is usually not aborted; if it is, the
;PC is SOS'ed regardless of the setting of %OPOPC.
;See the .MARA and .MARPC variables.
%PIMPV==20000 ;MPV (memory protect violation) [2] (S)
;The job referenced a non-existent memory location.
;The address of that location (roundd down to
;a page boundary on KA-10's) may be found in .MPVA.
;The guilty instruction was aborted, and the PC was
;left set according to %OPOPC.
%PICLK==10000 ;Slow (1/2 sec) clock [3] (A)
%PI1PR==4000 ;Single-instruction proceed [1] (S)
;If a job is started with the one-proceed flag
;(%PC1PR on KA-10's) set, after one instruction
;is completed a %PI1PR interrupt will occur.
;DDT's ^N command uses this feature.
%PIBRK==2000 ;.BREAK instruction executed. [1] (S)
;.BREAK is used for DDT breakpoints, and for explicit
;program requests to DDT.
%PIOOB==1000 ;Address out of bounds [2] (S)
;This is an obscure condition that used to
;happen on USR device IOT's, when an attempt
;was made to refer to a nonexistent location in the
;other job. Now this always causes an MPV.
;The guilty instruction was aborted, and the PC was
;left set according to %OPOPC.
%PIIOC==400 ;IOCERR (I/O channel error) [2] (S)
;This indicates the failure of an I/O system
;call. The channel that was being operated on is
;in .BCHN, and its .IOS word should contain, in
;bits 4.5 - 4.1, an error code.
;The guilty instruction was aborted, and the PC was
;left set according to %OPOPC.
%PIVAL==200 ;.VALUE instruction executed [1] (S)
%PIDWN==100 ;System-going-down status change [3] (A)
;If the system changes its mind about whether
;or when it is scheduled to go down, this interrupt
;is signaled.
%PIILO==40 ;ILOPR, ILUUO (illegal operation) [2] (S)
;This can be caused by a returnable uuo when the
;program's 41 doesn't seem suitable for handling one
;(see ITS UUOS). It can also be used to report
;the failure of certain more archaic system calls.
;The guilty instruction was aborted, and the PC was
;left set according to %OPOPC.
%PIDIS==20 ;Display memory protect [2] (A)
;The 340 or E&S display got an MPV.
;This is now obsolete since the 340 and E&S
;no longer work.
%PIARO==10 ;Arithmetic overflow [3] (S)
;The PDP-10's built-in arithmetic overflow
;condition was detected by the hardware.
;In fact, overflow occurs so often
;that enabling this interrupt causes the
;machine to slow down considerably,
;and it should be avoided.
%PIB42==4 ;BADPI (Bad location 42) [1] (S)
;If in attempting to interrupt a job it turns out
;to be necessary to refer to nonexistent memory
;or write in read-only memory, this interrupt
;is signaled, instead of MPV or WIRO.
;This is so that the program will return to DDT
;instead of mysteriously looping.
%PIC.Z==2 ;^Z or CALL typed on terminal [1] (A)
%PITYI==1 ;TTY input (obsolete) [3] (A)
;LH bits
%PJRLT==200000 ;Real-time timer went off [3] (A)
;These interrupts are controlled by the .REALT
;uuo. See ITS UUOS.
%PJRUN==100000 ;Run-time timer went off [3] (A)
;This interrupt is requested (in advance)
;by setting .RTMR.
%PJNXI==40000 ;Non-existent IO register [2] (S)
;A Job in User IOT mode referenced a non-existent IO
;register on the KS10 Unibus. The PC is left pointing
;before the guilty instruction. The address of the
;non-existant register may be found in .MPVA.
%PJJST==20000 ;Job Status display request. [3] (A)
;The sequence ^_J was typed on the
;console owned by this process or some inferior.
%PJDCL==10000 ;Deferred call. [1] (S)
;An attempt was made to read TTY input
;and the next character was a deferred-call
;character (^_D or Control-CALL).
;This deferred-call character is never seen
;by the program; it just causes the interrupt.
;It differs from ordinary CALL or ^Z
;in that it takes effect when the program
;gets around to reading it, not immediately.
%PJATY==4000 ;TTY returned. [3] (A)
;This interrupt happens when the TTY is
;returned by the superior, after having
;been taken away. TECO uses this to know
;that it must redisplay the entire screen.
%PJTTY==2000 ;Don't have TTY [2] (S)
;This results from an attempt to use the job's
;console tty when the job does not own it, if
;%TBINT is 1 and %TBWAT is 0. See ITS TTY.
;The guilty instruction is aborted, and the PC is
;left set according to %OPOPC.
%PJPAR==1000 ;Memory parity error [2] (A)
;Programs are not intended to try to recover
;from parity errors, on the assumption that they
;are probably permanently screwed up.
;This interrupt is asynchronous because it can
;be caused by a parity error in another job
;which destroys data in a page shared with this job.
%PJFOV==400 ;ARFOV (Floating overflow) [3] (S)
;This is a non-aborting PDP-10 hardware condition.
%PJWRO==200 ;WIRO (Write in read-only page) [2] (S)
;The guilty instruction was aborted, and the PC was
;left set according to %OPOPC. The address of read
;only location (rounded down to a page boundary on
;KA-10's) may be found in .MPVA.
%PJFET==100 ;Fetched insn from impure page [2] (S)
;On KA-10's, if bit %PCPUR of the PC flags is 1,
;fetching an instruction from an impure page
;will cause this interrupt. This is supposed to
;facilitate catching jumps to randomness.
;The guilty instruction is aborted, and the PC is
;left set according to %OPOPC.
%PJTRP==40 ;SYSUUO (System uuo in trap mode) [2] (S)
;A job whose .UTRAP variable was nonzero either
;attempted to execute an instruction that trapped
;to the system, or was about to be interrupted.
;This feature is intended to be used by the superior
;to provide a non-ITS environment for the inferior.
;For that purpose, this interrupt should not be
;enabled for the inferior, so that it will be fatal.
;The guilty instruction was aborted, and the PC was
;left set according to %OPOPC.
%PJDBG==2 ;System being debugged state change [3] (A)
;When the system enters or leaves "debugging mode",
;this interrupt is signaled.
%PJLOS==1 ;A .LOSE UUO or a LOSE system call [2] (S)
;was executed.
F. The Interrupt Bits in the Second Word
The right half of the second word (.IFPIR) is used for I/O channel
interrupts that signal the arrival of or need for data.
They should not be confused with I/O channel error interrupts
or IOCERRors. Each channel has its own bit: 1.1 is for channel
0; 1.2, for channel 1; ... 2.7, for channel 17 .
They are all class 3, and their significance depends on the device
open on the channel.
The left half of the second word (.IFPIR) is used for
"inferior got a fatal interrupt" interrupts. Each of a job's
inferiors is assigned its own interrupt bit from among the
bottom 8 bits of the left half. When an inferior job is created,
its interrupt bit should be read and remembered by reading the
.INTB variable with a .USET. Every time that inferior gets a fatal
interrupt, it will be stopped and the superior will receive an
interrupt on that inferior's bit in .IFPIR. The inferior may
be restarted by zeroing its .USTP variable, but if the fatal
interrupts remain and are still fatal the inferior will simply
stop and interrupt the superior again. "Inferior got a fatal
interrupt" interrupts are all class 3.
The reason that inferiors interrupt through a special set of bits
instead of using I/O channel interrupts is that it makes it possible
to receive interrupts from all one's inferiors without having them
all open on I/O channels at all times. DDT normally keeps only
its current job open, and when it receives an interrupt from some
other job it opens that job temporarily.

3571
doc/sysdoc/itstty.41 Executable file

File diff suppressed because it is too large Load Diff

782
doc/sysdoc/job.100 Executable file
View File

@@ -0,0 +1,782 @@
PROGRAMMING TECHNOLOGY DIVISION DOCUMENT SYS.xx.yy
IDENTIFICATIONî______________
The JOB/BOJ Device: A Mechanism for Implementing
Non-standard Devices
Marc S. Seriff, Jack Haverty, Richard Stallman (MIT-AI)
September 18, 1974
INTRODUCTIONî____________
It is occasionally desirable to extend the ITS system to allow
for the use of non-standard I/O devices. A very desirable feature
would be to allow user-level programs to make use of the newly defined
devices with out modification of the user-level programs. For this
reason the JOB/BOJ device was implemented.
When a job (call it the user) attempts an OPEN for a file whose
name is "JOB: <-dir>-; <-fn1>- <-fn2>-", the system creates a
new job, called the BOJ device handler, or BDH (this is a terrible
name; it USES the BOJ device and HANDLES the JOB device), and attempts
to load the file "DSK: <-dir>-; <-fn1>- <-fn2>-" into that job.
If the load fails, the OPEN will fail. If this load succeeds, the
OPEN, as well as all further I/O operations on the user's JOB channel
will be referred to the BDH for execution. At that point, it will be
up to the BDH to decide whether or not the open should fail. In order
to get a handle on information about the user's open, The BDH opens
one or more channels to the "BOJ" device. The system will insure that
the BDH's BOJ channel is logically linked to the user's JOB channel.
The following diagram illustrates what happens:
PTDD 2 SYS.xx.yy
__________ _________
| | | |
| User |------v__________------>| BDH |
|__________| | | ---XO--- | | |_________|
| | Sys|tem | |
____| |_____|_____| |____
|v | |v
The JOB channel | The BOJ channel
|
|v
System mediates
Once the BDH has successfully opened the BOJ channel, it will be
notified (via an I/O channel interrupt) every time the user attempts
an I/O operation on the JOB channel. The BDH may then examine the
data that is made available to it about the I/O operation and may
simulate the operation for the user. In this way, BDHs can be written
to give anything the appearance of a disk, tape or other specific type
of I/O device.
USING THE JOB DEVICEî_____ ___ ___ ______
Programs that use the JOB device should not be required to make
special provisions. A BDH should, in general, be written so that the
non-standard device will behave exactly like some standard device. In
other words, a user program may open a JOB device using a standard
open and may then execute any legal I/O operation.
A file name with something other than "JOB" for a device code can
be made to act like a JOB device in one of two ways. The first way
should be used for devices that are not generally applicable or are
expected to be used only for a short time. To use this method simply
use translates (using MONIT, DDT or directly via system calls) to
inform the system which file should be used as a BDH. For instance,
if we translate all file names of the form "XXX:" into the file name
PTDD 3 SYS.xx.yy
"JOB:ABC;TS RUNXXX", then the system will use the file "DSK:ABC;TS
RUNXXX" as the BDH for any file name whose device code is "XXX".
The other method is much simpler and is designed for non-standard
devices that are to be made available to the entire user community.
When an OPEN is attempted on a device whose name the system does not
recognize, the system will examine the "DEVICE;" directory for a file
whose first name is "JOBDEV" and whose second name is the unrecognized
device name. If such a file exists, then the contents of that file
will be loaded by the system and used as the BDH for the user's OPEN.
USING THE BOJ DEVICE - THE BOJ DEVICE HANDLERî_____ ___ ___ ______ _ ___ ___ ______ _______
The BDH is the workhorse in the JOB/BOJ device scheme. It is
required to interpret all of the user's I/O operations. It must do
everything to make the non-standard device that it represents appear
standard. The system provides five .CALLs to give the BDH some of the
required communcation with the user.
The first thing that the BDH should do when he is loaded and
started by the system is to execute an OPEN on the BOJ device. This
establishs a logical link between the user and the BDH. The BDH may
enable a channel interrupt on the BOJ channel, in order to be informed
whenever the user attempts an I/O operation.
It should be noted that the ITS system allows for the possibility
of a full duplex connection between the user and the BDH (i.e. a
channel in each direction). If a user attempts an open for reading
and an open for writing on the same device, then the system will
present both opens to the same activation of the BDH. Should this be
undesirable for a particular BDH, that BDH should use an open mode
with the 3.4 bit set (10 in the left half) each time it attempts to
open the BOJ device.
PTDD 4 SYS.xx.yy
JOBCAL SYSTEM CALLî______ ______ ____
The first .CALL that will be discussed is the JOBCAL. This call
enables the BDH to find out what I/O operation the user has attempted
to execute. It has the following calling sequence:
.CALL JOBCAL
... ; Error return
... ; Success return
JOBCAL: SETZ
SIXBIT/JOBCAL/
[<-BOJ channel number>-]
2000,,<-opcode>-
SETZ [-<-n>-,,<-data>-]
This .CALL, as well as the other three discussed below, will fail to
skip if any of the following conditions hold:
1. <-BOJ channel number>- is an illegal channel number.
2. <-BOJ channel number>- is not open on the BOJ device.
3. the user job does not exist or as has closed his channel.
4. the user job is no longer attempting to execute the I/O
operation.
<-opcode>- should be an address into which information about
the I/O operation requested will be placed. This word contains three
sections. The right half of the word contains an integer indicating
which operation was attempted. The following table indicates what the
various integers mean:
PTDD 5 SYS.xx.yy
CODE OPERATIONî ____ _________
0 OPEN
1 IOT (transfer)
2 STATUS (currently unused)
3 RESET
4 RCHST (complete status)
5 ACCESS
6 FDELE (for delete or rename while not open)
7 FDELE (for rename while open)
8 CALL (see below)
It is up to the BDH to insure that these I/O operations perform as
they would for standard ITS devices.
The top three bits (4.9-4.7) of the op-code word contain the mode
in which user is attempting to open his channel. This is only
meaningful for op-code 0, OPEN. If either of the next two bits (4.6
and 4.5) are non-zero, then the user is requesting that a channel be
closed. As was mentioned above, the system allows the connection
between user and BDH to be full dumplex. If the 4.6 bit of the opcode
is set, then the user is requesting that his input channel be closed,
while the 4.5 bit requests a close of the user's output channel. It
is possible to get an opcode in which both bits are set. In the case
the BDH should perform the obvious task of closing both channels.
Most I/O operations require more information than just the name
of the operation. The third argument to JOBCAL tells the system where
any additional information that is available should be placed.
<-n>- is the largest number of words that the BDH is willing to
PTDD 6 SYS.xx.yy
accept (it should normally be 12). <-data>- is the address where
the first word of the information should be placed. What information
is placed in this buffer is determined by the I/O operation being
attempted.
If the op-code (in the right half of the op-code word) is less
than 8, then five words will be written into the buffer (beginning at
<-data>-) in response to the JOBCAL. The meanings of the words are
given in the following table:
PTDD 7 SYS.xx.yy
WORD OPERATIONS MEANINGî____ __________ _______
1 IOT (1) Meaningful only for block IOTs.
This word will contain the user's
IOT pointer. The left half of this
word will be the negative of the
number of words that the user wants.
1 ACCESS (5) The address within the virtual file
that is open from (or to) which the
next IOT should be done. The first
word of the virtual file is word
zero.
1 FDELE (6 or 7) Zero implies delete requested.
Non-zero means that a rename is
requested. This word is the name
(in sixbit) to be used as the new
first file name.
2 OPEN (0) or FDELE (6) First name of the file that the user
is attempting to open, rename or
delete.
3 OPEN (0) or FDELE (6) Second name of the file that the
user is attempting to open, rename
or delete.
4 OPEN (0) or FDELE (6) Name of directory to be used for
open, rename or delete.
5 OPEN (0) or FDELE (6) Name of device to be used for open,
rename or delete.
6 OPEN (0) The full 18 bit open mode (right
justified).
6 FDELE (6 or 7) Zero implies delete. Non-zero means
that a rename is requested. This
word is the name (in sixbit) to be
used as the new second file name.
If the op-code returned by JOBCAL is 8, then the user has
attempted some I/O operation not recognized by the systems JOB/BOJ
device code (this does not mean that the operation is illegal). Inî ___
this case, more information is written into the BDH's buffer (up to
twelve words). The first of the data words will be the SIXBIT name of
PTDD 8 SYS.xx.yy
the operation being performed. (This will normally be the name of the
.CALL executed by the user - see Appendix 1 for a list of
possiblities.) The second word will contain all of the flags that the
user has set using the "flag" feature of the .CALL UUO. The third
word will be an integer indicating how many input (to the system)
arguments the user supplied in his .CALL. It should be noted that if
this integer is larger than <-n>-+3, then some information will be
lost. The values of the input arguments will appear in the remainder
of the words in the buffer. Remember that, in almost all cases, the
first of the input arguments will be the user's channel number.
JOBRET SYSTEM CALLî______ ______ ____
Once the BDH has interpreted the user's request for execution of
an I/O operation, the BDH must have some way of responding to the
user. This is provided with the JOBRET .CALL. This .CALL serves
three purposes:
1. to unblock the user who is waiting for completion of his
I/O request (possibly causing the request to skip)
2. to set lossage codes in the user's status words (e.g. for
failed opens).
3. to return information requested by the user's I/O
operation.
The format of this CALL is as follows:
.CALL JOBRET
... ; error return
... ; success return
JOBRET: SETZ
SIXBIT /JOBRET/
[<-BOJ channel number>-]
[<-return>-]
SETZ [-<-n>-,,<-data>-]
where <-return>- satisfies requirements 1 and 2 above. If
PTDD 9 SYS.xx.yy
<-return>- is zero, then the user's I/O call will not skip or set
status bits. If <-return>- is of the form <-i>-,,<-j>- , then
<-i>- will be placed in the "open-loss" field of the status word for
the user's channel and the user's I/O call will skip <-j>- times. A
list of all currently recognized open loss codes can be found in
Appendix 2.
If the user's I/O call requested data, then the BDH can supply
this data by supplying the third argument to the JOBRET call. The
system will use the <-n>- words beginning at location <-data>- as
the values for the return arguments in the user's call.
SETIOC AND JOBINT -- INTERRUPT SYSTEM CALLSî______ ___ ______ __ _________ ______ _____
There are two interrupt oriented functions that the BDH must
perform and there are CALLs available to perform them. The first is
to notify the user when he has done something catastrophic. The user
should be notified of his error by causing the system to awaken him
with an I/O channel error. This done with the SETIOC call, as
follows:
.CALL SETIOC
... ; error return (standard reasons
+ illegal IOCERR code)
... ; success return
SETIOC: SETZ
SIXBIT/SETIOC/
[<-BOJ channel number>-]
SETZ [<-IOCERR code>-]
where <-IOCERR code>- is an integer identifying the reason for the
error. This integer should be chosen from the list that can be found
in Appendix 2. Since BDHs are written to handle non-standard devices,
these error codes will quite often not apply. Simply choose the code
that comes closest.
PTDD 10 SYS.xx.yy
Occassionally, the BDH must notify the user of a non-catastrophic
situation (e.g. the arrival of data). The JOBINT call allows the BDH
to give the user a second-word I/O channel interrupt, as follows:
.CALL JOBINT
... ; error return
... ; success return
JOBINT: SETZ
SIXBIT /JOBINT/
SETZ [<-BOJ channel number>-]
JOBSTS SYSTEM CALLî______ ______ ____
Finally, the BDH must have some way to notify the system what the
status of the pseudo-device is. For this purpose, the JOBSTS call is
available. Its calling sequence is as follows:
.CALL JOBSTS
... ; error return
... ; success return
JOBSTS: SETZ
SIXBIT /JOBSTS/
[<-BOJ channel number>-]
SETZ [<-new status>-]
The right half of <-new status>- will be given to anyone requesting
the status of the user's channel until another JOBSTS is done. It
should be remembered that the low order six bits (1.1-1.6) should
contain the device code of the pseudo-device. Unless, you know what
you are doing, this should always be 22 octal.
DATA TRANSFERS - HOW TO IOTî____ _________ _ ___ __ ___
Since the main purposes of I/O devices is transfer of
information, let us look at how the BDH manages to respond to the
user's IOTs. The method for doing this is very simply. If we think
back to the diagram presented early in this memo, we will remember
PTDD 11 SYS.xx.yy
that the BOJ and JOB channels (i.e. the channels belonging to the BDH
and the user, respectively) are logically connected. The full meaning
of this now becomes clear. If the JOB channel is open for input and
the BOJ channel is open for output, then anything that BDH outputs on
the BOJ channel will be available to the user as input on the JOB
channel. (For this reason, the BDH must insure that he opens the BOJî ____
channel in the opposite direction from the user's JOB channel even if
this requires opening the BOJ channel a second time in the correct
mode.)
There are two features of which the BDH implementer should be
aware when writing the I/O sections of the BDH. Let us assume for the
discussion here, that the user has the JOB channel open for reading
and that the BDH has the BOJ channel open for writing. Let us also
assume that the user is currently hung attempting to read 100 words on
his JOB channel.
First it should be noted that the BDH does not have to respond toî ___
this request with a single transfer of 100 words. The system will act
as an mediator between different transfer sizes. The BDH can respond
to the user's request for 100 words in several ways:
1. He can send all 100 words in small pieces (e.g. 10
transfers of 10 words each.
2. He can send all 100 words in a single transfer.
3. He can send more than 100 words. In this case, the BDH
will remain hung in his IOT until the user has read all of
the data that the BDH is attempting to send. (If this is
undesirable, set the 3.5 in the BOJ open mode. This will
cause BOJ IOTs to unhang whenever the user's IOT is
PTDD 12 SYS.xx.yy
satisfied. When that happens, the BOJ IOT pointer will
have been counted out only partially; the RH will point to
the first word not transfered)
4. He may send less than 100 words. In this case, the BDH
must manually awaken the user as described below.
The user, who is hung awaiting his 100 words, will stay hung until he
has received all 100 words. Suppose, however, that the BDH only
wishes to send 50 words (e.g. the last 50 words of the virtual file).
To do this, he can send the 50 words normally, but must then use the
JOBRET call (described above) to awaken the user. JOBRET should be
called with the BOJ channel number as the first argument, zero as the
second argument and no third argument. Secondly, the BDH implementer
must be aware that the ITS system guarantees that IOTs to a channel
open in block mode, will never generate an I/O channel error. In
other words, the following algorithm should be followed:
1. If the user requests n words and there are n words or more
left in the "file", give him n words.
2. If the user requests n words and there are only m words
(n>m), give him m words and manually awaken him (using
JOBRET).
3. If the user requests n words and there are no words left,
then give him nothing and manually awaken him (using
JOBRET).
HINTS TO BDH IMPLEMENTERSî_____ __ ___ ____________
The following hints should ease the task of BDH implementers a
little. It is hoped that anyone who attempts to a BDH implementation
will add his harshly acquired knowledge to this section of this memo.
PTDD 13 SYS.xx.yy
1. Remember that the BDH is essentially a disowned job and should
attempt to log out after a close has been requested.
2. Be very leery of logging out for any reason other than a requested
CLOSE. In particular:
a. if a JOBCAL fails, only log out if a request for OPEN has not
yet been received.
b. when you generate an I/O channel error for the user, only log
out if the error is irrecoverable. Remember that he can
correct an access beyond end-of-file by doing an access before
attempting another IOT.
c. if he requests an I/O operation that you do not recognize,
generate a "mode not available" error (via JOBRET) and wait
for his next request.
d. if you decide, for your own reasons, to make the initial open
fail, you should log out.
THE OJB DEVICE -- AN AID FOR DEBUGGING THE BDHî___ ___ ______ __ __ ___ ___ _________ ___ ___
One of the problems with debugging BDH programs is that when the
JOB device is used, it is loaded into a newly created job. That job is
not inferior to any DDT, and there is no way to put breakpoints in it
before it starts. The OJB device makes it possible to run the BDH
program under DDT.
The OJB device acts just like the JOB device except during the
initial open. When the JOB device would be creating and loading a new
job, the OJB device is looking for an existing job whose UNAME and
JNAME are the same as the filenames specified in the open. If such a
job is found, it is connected to the job opening the OJB device
through a standard JOB-BOJ pipeline. If such a job does not exist,
PTDD 14 SYS.xx.yy
the open of the OJB device fails. In order to protect innocent jobs
from being hacked in this matter, the job opened on the OJB device is
required to have set its OPTOJB bit (this is bit 4.2 in the .OPTION
varisble, settable with .SUSET). Also, it must not already be a BDH,
for the system cannot consider one job to be a BDH through two
connections at once. If either of those conditions is not met, the
OJB open WAITS until they are.
To remove a possible timing screw, a BOJ device open by a job
that is not a BDH, which usually fails, will wait instead for the job
to become a BDH if the job's OPTOJB bit is set.
The procedure for using the OJB device for debugging is:
1. create a job to use for the BDH (call it J, in this example).
2. run (in another job) the program which would normally open
the JOB device, but tell it (perhaps by means of a translation) to use
the OJB device instead. This program's function is to issue system
calls so that the BDH's responses to them can be tested.
Since the OPTOJB bit of job J is now 0, when this program reaches
the OJB open it will hang.
3. ^Z that program, and ^P it. it will go back to hanging in the
open of the OJB device.
4. switch to job J, load in the BDH program. This RESET's the
job so that if it had been a BDH before, it will not be one now.
5. turn on the OPTOJB bit by depositing from DDT in .OPTION.
The conditions for a successful OJB open by job JJ have now been met,
so that job will make some headway, turning job J into a BDH and
waiting for job J to issue a JOBRET.
PTDD 15 SYS.xx.yy
6. it is now possible to start running job J, with breakpoints
as desired, to step through the code for handling the initial open.
It is unlikely, but theoretically possible, for J to execute its BOJ
open before JJ gets around to turning J into a BDH. In this case, J
will wait for JJ to do so.
7. if it becomes necessary to try again after discovering a bug,
go back to step 2. The OJB open will hang up this time not because
the OPTOJB bit is off (since it is still 1) but because J is already a
BDH. Loading J in step 4 will make J cease to be a BDH but also turn
off the OPTOJB bit, so JJ will still be waiting.
8. it is possible for job JJ to be "PCLSR'ed" or backed up out
of its open while job J is being traced through the handling of the
initial open. For example, job JJ might receive a real-time
interrupt. If that happens, J will cease to be a BDH. This will not
interfere with the tracing of J until the next BOJ device system call
is executed; that call will probably fail. It is impossible to
continue after such an occurrence, so the jobs must be restarted by
returning to step 2. Of course, if there are no breakpoints before
the first JOBRET, this is very unlikely to happen.
9. if the initial open has been handled successfully, to go on
to debug handling of other system calls, simply tell JJ to execute
them with J stopped while JJ is being told, then ^Z^P JJ and go back
to J.
10. the usual .LOGOUT in the BDH program will be a no-op when the
program is run as an inferior in this manner, so it should be followed
by a .VALUE.

360
doc/sysdoc/locks.108 Executable file
View File

@@ -0,0 +1,360 @@
-*- Text -*-
This file contains documentation for both the LOCK device,
and the locked switch list and critical routine features.
THE LOCK DEVICE. [ In ITS version 1630 and later ]
The LOCK device provides a simple and foolproof technique for interlocking
between jobs. While not as efficient as using an AOSE-style switch in
shared memory, the LOCK device is much easier to use and is suitable for
use in those situations where a lock is only rarely seized, and is only
held for brief periods of time.
Locks are identified using a single SIXBIT word as a lock name. (Actually,
and non-zero 36-bit word can be used.) A job can lock the FOO lock by
opening "LOCK:FOO" for output. The LOCK device ignores any second filename
or directory name you might supply. The lock will be released when the
channel is closed. As long as the job keeps the lock channel open, any
other attempts to lock the same lock result in a %ENAFL (FILE LOCKED)
error.
When opening the LOCK device, bit 1.4 indicates that the opener wishes to
hang waiting for the lock, rather than receiving a %ENAFL error.
It is also possible to receive a %EFLDV (DEVICE FULL) error when opening
the LOCK device if the table of currently held locks that ITS maintains
overflows.
Here is the registry of all lock names. Any program that uses the LOCK
device should register the name of the locks it uses here.
Name Purpose
------ ------
NUTMEG This lock is used in an example later
on in this file.
MBXxxx The set of locks whose names start with the
characters "MBX" are used by COMSAT and GMSGS to
coordinate access to mailboxes. The algorithm for
computing the lock for the mailbox named
SNAME;NAME1 NAME2 is:
MOVE A,NAME1
ROT A,1
ADD A,NAME2
ROT A,1
ADD A,SNAME
IDIVI A,777773 ; Largest prime < 1,,0
HRLI B,(SIXBIT /MBX/) ; Result in B = A + 1
THE LOCKED SWITCH LIST AND CRITICAL ROUTINE FEATURES.
There is an obvious technique for interlocking between jobs on
the PDP-10 - namely, the use of AOSE - which has been unusable
under ITS simply because a job might be killed while it had a
switch locked, thus causing the switch to remain locked forever.
These implemented features allow that problem, and the similar
problem of system crashes while a switch in a permanent data
base is locked, to be solved without any loss of efficiency.
The locked switch list feature allows a program to maintain a
list of switches which it has locked, so that ITS can unlock
them when the job is killed (or logs out, or is gunned)
or is reset (for example, $l'd by DDT). The critical routine
feature allows the program to cause ITS to perform certain
actions if the job is killed or reset with the PC in a specified range.
These features do not prevent bugs in the programs accessing
a switch from causing the switch not to be unlocked. They make
possible successful interlocking but do not guarantee it.
A. THE DEFINITIONS OF THE FEATURES.
These features are all activated by setting the %OPLOK bit in
the .OPTION USET-variable to 1 (This bit is 1000,,). If that is
not done, words 43 and 44 are not in any way special. Also, the
addresses used do not have to be 43 and 44; that is merely their
default values. The actual adresses used are relative to the
contents of the .40ADDR USET-variable, which initially contains
40 . If .40ADDR were set to 1000, locations 1003 and 1004 would
used. Of course, all system actions that normally use locations
40, 41 and 42 would use 1000, 1001 and 1002.
1. THE LOCKED SWITCH LIST.
When the %OPLOK bit is 1, location 43 is taken to be the pointer
to the job's locked switch list. The list pointer
should either be 0, meaning the list is empty, or the address of
the first two-word switch block. The format of a switch block is
as follows:
1st word: the switch, or, if the indirect bit is set in
the second word, the address of the switch
(multiple indirection is not allowed).
2nd word: the RH holds the address of the next switch
block, or 0 (this is the CDR of the list).
the LH holds the instruction to be executed to
unlock the switch. The index field is ignored.
The instruction must either be an AOS or SOS
with 0 in the AC field, a logical instruction
(such as SETAM, IORM, SETOM, ANDCAM), a halfword
instruction, a MOVEM, MOVNM, MOVSM, MOVMM,
ADDM or SUBM. The AC will never be modified
even if the instruction
says to do so. If the LH is 0, the instruction
SETOM is used, as the most common choice.
When the job is killed or reset, if the locked switch list is
not null, the system looks at the first switch block, unlocks
the switch by executing the unlock instruction with the switch
word as its memory argument, and the copying the RH of the
second word of the switch block into 43 to remove the block
from the list (this makes sure that no switch is ever unlocked
twice due to PCLSR'ing).
This procedure is repeated until 43 contains 0,
thus unlocking all the switches in the list. Obviously since the
job's pages are about to be discarded this action will have no
consequence unless the switches are in pages shared with other
jobs.
If in the process of unlocking the switches
the system tries to read from a nonexistent page or write in a
pure page, it gives up entirely, ignoring the rest of the
locked switch list, and also the critical routine table. Also
if the end of the list is not reached after 512. switch blocks
have been unlocked, the system gives up.
2. THE CRITICAL ROUTINE TABLE.
When the %OPLOK bit is 1, location 44 is considered to be an
AOBJN pointer to a table of critical sections of code, which are
involved in the manipulation of switches or the locked switch
list. The table should be a vector of two-word entries, one for
each critical section of code. The first word of each entry
should give the boundaries of the critical section: the left
half should have the the address of the first instruction of the
critical section; the right half, the address of the first
instruction after the critical section. The second word of the
entry should have an unlock instruction, subject to the same
restrictions as for locked switch list unlock instructions,
the only difference being that the address field of the
instruction is taken from the RH of the word, as one would expect,
whereas in unlock instructions in switch blocks the address of
the switch block is used, and the RH of the word is the CDR.
Examples will make all this clear.
If the job is killed or reset while the PC is in the range
specified by a critical routine table entry, the switch
specified by the entry will be unlocked by executing the unlock
instruction. It is possible
for the ranges specified by two entries to overlap; to make sure
that no entry is processed more than once, the system updates 44
as it processes each entry.
As with the switch list unlocking, the system abandons the whole
thing if it needs to read or write in a page that won't allow it.
3. FATAL INTERRUPTS IN TOP-LEVEL JOBS WITH LOCKED LOCKS.
When the %OPLKF bit in a job's .OPTION variable is set to 1, and if the job
is the top-level job of a non-disowned tree, then if that job ever receives
a fatal interrupt its locks will be unlocked by the system job as part of
the process of detaching it. Thus fatal interrupts in network servers,
toplevel DDTs, system demons, etc. that happen while those jobs have shared
databases locked, will not keep other jobs blocked waiting for someone to
gun down the corpse.
The reason you might not want to set %OPLKF is that after a jobs locks are
unlocked, it will not in general work to proceed the job. Such a detached
corpse will only be good for autopsy, not revival.
B. USING THE FEATURES FOR SWITCHES IN A SHARED PAGE.
In this section it is assumed that the page is not part of a
disk file, and will not survive through a system crash. That
means that it is not necessary to worry about unlocking switches
that are locked at the time of a system crash.
1. LOCKING AN AOSE-STYLE SWITCH.
The proper routine to use for locking a switch follows:
The address of the two-word switch block is assumed to be in A.
LOCK: AOSE (A) ;LOCK THE SWITCH, OR WAIT TILL WE CAN.
.HANG
LOCK1: MOVE B,43 ;PUT THE SWITCH ON THE
HRLI B,(SETOM)
MOVEM B,1(A) ;LOCKED SWITCH LIST
MOVEM A,43
LOCK2: POPJ P,
This routine will set up the switch as a switch block, and make
43 point to it. The contents of the switch block will be:
0 ;This word is the switch itself!
SETOM <previous contents of 43>
;The SETOM is the unlock instruction.
;The RH has nothing to do with the SETOM;
;it points to the next block of the list.
Note that the HRLI instruction is superfluous, because 0 in the
left half of the second word of the block is the same as (SETOM).
The three instructions starting at LOCK1 are critical because
the switch has been locked but is not on the locked switch list.
Therefore, an entry in the critical routine table of the form
LOCK1,,LOCK2
SETOM @A
is needed, in case the job is killed while executing there.
2. UNLOCKING AN AOSE-STYLE SWITCH.
The correct way to unlock a switch follows:
(assuming that A points to the switch block and that
the switch block is the first item on the locked switch list).
UNLOCK: HRRZ B,1(A) ;REMOVE THE SWITCH FROM THE
MOVEM B,43 ;LOCKED SWITCH LIST.
UNLOC1: SETOM (A) ;THEN UNLOCK THE SWITCH.
UNLOC2: POPJ P,
The instruction at UNLOC1 is critical because the switch is
locked but not on the locked switch list. Therefore, an entry
is needed in the critical routine table as follows:
UNLOC1,,UNLOC2
SETOM @A
Note that the switch must be removed from the list before
unlocking. That is because if the switch is locked but not on
the list, the critical routine table may be used to unlock it,
but if the switch is on the list but not locked, it will be set
to -1 if the job is killed, and that could cause problems if
some other job had locked the switch.
C. HANDLING SWITCHES IN DISK FILES.
The extra problem here is to make sure that if the system crashes, the next
time the data base is accessed after the system is reloaded all the
switches will be reinitialized. This may be done by using the time and
date that the system was started to distinguish different incarnations of
it.
The technique uses a variable INITDN, stored in the database, and a LOCK
device lock named "NUTMEG". Whenever a program accesses the database for
the first time, it must check INITDN. If INITDN does not equal the time
the system was started, the database requires initialization. If a job
detects that the database requires initialization, it seizes the NUTMEG
lock, checks to see that initialization really is required, performs the
initialization, updates INITDN, and releases the lock.
The skeleton of the necessary routine is as follows, assuming that the file
has already been opened and its pages mapped into core with a CORBLK system
call, and INITDN is the address of the variable and SWIT1, SWIT2, etc. are
the addresses of switches.
INIT: .CALL [ SETZ ? SIXBIT /RQDATE/
MOVEM A ; Ignore 1st value
SETZM A] ; 2nd value is time of system startup.
.LOSE 1000
JUMPL A,[MOVEI A,300. ; System doesn't know time,
.SLEEP A, ; Sleep 10. sec and hope it
JRST INIT] ; finds out the time.
CAMN A,INITDN ; Init needed?
POPJ P, ; No => No need for the lock, just return.
.CALL [ SETZ ? SIXBIT /OPEN/
MOVSI 10\.UAO ; 1.4 => Hang waiting for initialization lock
MOVEI CH
MOVE [SIXBIT /LOCK/]
SETZ [SIXBIT /NUTMEG/]] ; Registered, database specific lock
.LOSE
CAMN A,INITDN ; Init needed?
JRST INIT1 ; No => someone else did it, unlock and return.
SETOM SWIT1 ; Start setting switches to unlocked
SETOM SWIT2 ; state. These insns should address
SETOM SWIT3 ; locations in the mapped file pages.
;; etc.
SETOM SWIT9
MOVEM A,INITDN ; Mark init complete.
INIT1: .CLOSE CH,
POPJ P,
Note that the first CAMN A,INITDN can be omitted, and the algorithm is
still correct, but the second CAMN A,INITDN can -not- be safely omitted.
D. REFERENCE COUNTS.
Sometimes it is desirable to keep a count of the number of jobs
looking at a data base. When the count is AOS'd, an entry must
be put on the locked switch list to cause it to be SOS'd if the
job is killed. For example, assuming that A points to the count
and B points to an available two word block of memory:
LOOK: AOS (A)
LOOK1: MOVEM A,(B)
MOVSI C,(SOS @)
HRR C,43
MOVEM C,1(B) ;SET UP UNLOCK INSN & CDR POINTER.
MOVEM B,43 ;PUT THE BLOCK ON THE LIST.
LOOK2: POPJ P,
The critical code table entry needed is:
LOOK1,,LOOK2
SOS @A
When finished looking, the count must be SOS'd, and removed from
the list. The following routine will work, assuming only that
the block at the front of the list was put on by the LOOK routine
above:
UNLOOK: MOVE B,43
HRRZ A,(B) ;GET ADDRESS OF THE COUNT VARIABLE TO BE SOS'D .
HRRZ B,1(B) ;GET CDR POINTER.
UNLOO1: MOVEM B,43 ;REMOVE BLOCK FROM LIST.
UNLOO2: SOS (A) ;DECREMENT THE COUNT.
POPJ P,
The critical code table entry needed is:
UNLOO1,,UNLOO2
SOS @A
E. THE .HANG INSTRUCTION.
The .HANG UUO is to make it easy for programs to wait for various
conditions, such as locks becoming unlocked. It should be used the way a
JRST .-1 would be used in a stand-alone program. .HANG is documented
completely in .INFO.;ITS UUOS.
F. THE UNLOCK SYSTEM CALL.
The UNLOCK system call can be used to unlock the switches of a specified
job. Usually this is used by a job to unlock its own switches, but it can
be used on the switches of any job that the executing job is allowed to
write.
Usual case:
.CALL [ SETZ ? SIXBIT /UNLOCK/
SETZI %JSELF ] ; Unlock all my switches
.LOSE %LSSYS
(Note that this has nothing to do with the LOCK device. In particular it
will -not- close LOCK device channels.)

206
doc/sysdoc/magtap.101 Executable file
View File

@@ -0,0 +1,206 @@
MAG TAPE SPECS
Copied from memo from S.Cutler 2/23/72
THIS MEMO CONTAINS MANY LOWER-CASE CHARS
Bits in left half word of .OPEN call:
3.1=1,,0
0=> Input
1=> Output
3.2=2,,0
0=> Unit
1=> Block
3.3=4,,0
0=> ASCII
1=> Image
3.4=10,,0
0=> Ignore record gaps,treat them as part of the hardware
1=> "Chunk mode." [does not appear to be implemented any more]
If output then write an EOR gap after each .IOT.
If input, if user defined block IOT pointer is big enough
one record is read. See .IOT for details. Must be
opened in block mode.
3.5=20,,0
0=> Skip to EOF on last close on read
1=> Don't " " " " " " "
3.6=40,,0
0=> Odd parity
1=> Even parity
3.7,8=300,,0
00=> default (800 or 1600 BPI depending on drive type)
01=> 800 BPI (used to be 200 BPI)
10=> 1600 BPI (used to be 556 BPI)
11=> 6250 BPI (used to be 800 BPI)
3.9=400,,0 Only meaningful for 9 track tapes
0=> Core dump mode, 36 bit words, any density allowed.
1=> IBM Character Mode, 32 bit words, doesn't allow 200/556 BPI
4.1,2,3=7000,,0
0=> 2000=1024. words per record
1=> 1000=512. WPR
2=> 400=256. WPR
3=> 200=128. WPR
4=> 100=64. WPR
5=> 40=32. WPR
6=> 20=16. WPR
7=> 10=8. WPR
Open error if:
1) Open for writing and
a) Open for reading on another channel
b) Tape write locked (i.e. no ring)
c) IBM mode and less than 800 BPI
2) Open for reading and already open for writing on another
channel
3) Transport not on line
4) Chunk mode and not block mode
.IOT CHNM,LOC
-------------
For standard .OPEN, this works as a standard .IOT. If open
in chunk mode input [not implemented any more], loc has
loc/ -count,,loc2
where count is a number greater than the possible number of words to
be written into core. The .IOT causes words to be read into core
starting at loc2. For each word read, the count in decreased by one.
An IOC error occurs if the count is too small to contain the
record.
On chunk mode output, an EOR gap is written after each .IOT,
and the tape is written after each .IOT instead of waiting for
system buffers to fill or the channel closed. [not implemented any more]
.CLOSE CHNM,
------------
Closes the channel, releases the transport if not open on another
channel. Writes out all buffers in the system and writes 2 EOF
marks if open for writing, and backs up over second one.
.STATUS CHNM,LOC
----------------
1.1-1.6=> physical device code (15)
1.7-1.9 mode open in
2.1=> System buffering capacity empty (i.e. 0=> data read from
tape and not yet transferred to user by a .IOT or data
.IOTed from the user to the system but not actually
written onto tape or user core image.)
2.2=> System buffering capacity full (i.e. no core in which to
allocate buffers for reading from tape. Also too many
buffers resident in system but not yet written onto either
tape or users core image.)
2.3=> 1=> Beginning of tape
2.4=> 1=> End of tape
2.5=> 1=> 9 track, 0=> 7 track
2.6=> 1=>IBM mode, 0=> core dump mode
2.7=> Transport idle (no pending command)
2.8=> EOF (last thing seen was a tape mark)
Left half standard.
.RCHST AC,
----------
AC/ CHNM,,LOC
LOC: 0) 0,,(SIXBIT /MTn/)
1) 0
2) 0
3) 0
4) -1
.MTAPE AC,
----------
AC/ CHNM,,COMAND
COMAND/ COUNT,,FUNCTION
Right half of COMAND
0=> Hang until all tape motions finish
1=> Rewind
2=> Rewind and unload (also shreds tape leader)
3=> Write EOR. Writes out current system buffers even if
less than record size and writes an EOR gap.
4=> Write 3 inches of blank tape
5=> Write EOF. (Two EOF's are written automatically
after a close on a channel open for writing.)
6=> Space forward COUNT records. COUNT=0 implies 1
record. COUNT negative implies space reverse. Stops
at EOF or BOT.
7=> Space forward +- COUNT files. (Stops at BOT or
logical EOT.)
8.=> Space forward to logical EOT, back up over second
EOF.
9.=> Stop and reset the tape system.
10.=> Set write record size to COUNT words.
11.=> Read into AC write record size or size of last record
gobbled by an input IOT.
Skips if successful.
Rewind and space only if open for reading.
Write EOR, 3 inch, EOF writing only.
Stop and hang for both read and write.
Transport State Notes
--------- ----- -----
A transport turned off or off line is equivalent to not being there.
Tape can not be written unless the write enable ring is in the hub
of the tape.
A transport can be opened by an arbitrary number of channels in
different modes, but can not be opened by more than one user, or in
both input and output. The device dependent bits (3.4-4.9) must be
the same for all channels with the exception of chunk mode.
The logical end of tape (EOT) is located after two EOF's in a
row. A close on a channel open for writing writes two EOF's and
then backspaces over one of them. The .MTAPE command to go to
the end of the tape also backspaces over the second EOF.
If the physical end of tape mark is reached while writing a record,
the record is finished being output (there is always room for a few
records after the reflective strip) and an IOC error is raised
saying End of Tape.


841
doc/sysdoc/ncp.100 Executable file
View File

@@ -0,0 +1,841 @@
Warning- don't believe everything in this file!
ITS NCP INTERFACE
CALL: .OPEN
FUNCTION: OPEN channel to Network
ARGUMENT TEMPLATE:
1. Channel number in AC field of .OPEN instruction
2. 4 word block addressed by @ E (X) field of
.OPEN instruction
4 word block has this form:
_________________________________________________
| | |
| MODE BITS | SIXBIT /NET/ |
|_______________________|_______________________|
| |
| LOCAL SOCKET |
|_______________________________________________|
| |
| FOREIGN SOCKET |
|_______________________________________________|
| |
| FOREIGN HOST |
|_______________________________________________|
MODE BITS
|--------- don't buffer more
| output than allocation
|
| |----- 0-200 words
| | 1-2000 words
| |
____________________________________________________________________________
| | | | | |out|big|by- lis gen|im- |
| | SIZE OF BYTE | | |ctl|buf| te ten sok|age blk out|
|___________|___________|___________|___|___|___|___|___|___|_#_|___|___|___|
| | | | |_____|
BYTE SIZE IF | 0-"NORMAL" | | | |
MODE=44 __| 1-8 BIT BYTE SIZE _______| | |
(BYTE & IMAGE) IF ASCII | | STANDARD
USE BYTE FIELD | | ITS
IF IMAGE | | MODES
| | ______________
0-"NORMAL" | | | |
1-LISTEN ON ___________| | | 0XX ASCII |
LOCAL SOCKET | | 1XX IMAGE |
| | X0X UNIT |
0-USE LOCAL | | X1X BLOCK |
SOCKET FIELD | | XX0 INPUT |
1-GENERATE _______________| | XX1 OUTPUT |
"UNIQUE" SOCKET |____________|
# (USE .RCHST
TO FIND OUT
RESULT)
LOCAL SOCKET
32 bit socket # for local identification
FOREIGN SOCKET
32 bit socket # determined by foreign host
system
FOREIGN HOST
8 bit socket # specifying computer system
with which to contact
RETURNS: None
SKIPS: No Skip If Fails
FAILURE RETURNS:
Indicated in LH of .STATUS value (low order 6 bits
in LH)
i.e. .STATUS ch, ac
LDB ac, [220600,,ac]
CODE____
2 "WRONG DIRECTION"
(gender of socket wrong for mode)
6 "DEVICE FULL"
(socket table full)
7 "DEVICE NOT READY"
(NCP not up, or IMP not up)
13 "FILE ALREADY EXISTS"
(socket already open by you on another channel)
22 "CONTRADICTORY OPEN"
(byte size mismatched)
23 "FILE LOCKED"
(socket number not part of your allocated
"unique" group of 8 allocated to your job)
41 "OTHER END OF PIPELINE GONE OR NOT OPEN"
(HOST dead or non-existant see NETHST call)
SIDE EFFECTS:
EXAMPLES:
;to listen .OPEN ch, listen
JRST fail
.
.
Listen: 20,,'NET
1 ;waiting socket
0 ;socket determined when
matching RFC received
0 ;host determined when
matching RFC received
:to get "unique socket"
.OPEN ch, unique
JRST fail
:Unique 10,,'NET
0 ;determined by system
1305 ;foreign socket
6 ;foreign host
Equivalent:
.CALL OPEN
arg 1 mode,,channel number
arg 2 SIXBIT/NET/
arg 3 local socket
arg 4 foreign socket
arg 5 host number
CALL: .RCHST
FUNCTION: Read extended STatus of network CHannel
ARGUMENT TEMPLATE: AC/ channel,,
RETURNS:
WORD _________________________________
| | |
0 | | 'NET |
|_______________|_______________|
| |
1 | LOCAL SOCKET |
|_______________________________|
| |
2 | FOREIGN SOCKET |
|_______________________________|
| | | BYTE | |
3 | I | (reserved)| SIZE | HOST |
|___|___________|_______|_______|
| | |
4 | IMP DOWN | STATE |
|_______________|_______________|
| | |
5 | (reserved) | CLS |
|_______________|_______________|
| | |
6 | (reserved) | #BITS |
|_______________|_______________|
INTERRUPT
4.9 bit of word 3
set by receipt over network of INR/INS
control message (see protocol)
cleared by .RESET
causes interrupt on channel
BYTE SIZE
9 bit field
byte size of connection (bits 2.9 - 2.1)
HOST
9 bit field (8 used by Network foreign host #)
IMP DOWN
time in 1/30 sec. until IMP going down
(if planned)
-1 not going down
0 down
+n planned to go down in n/30 sec.
(see also NETIMP call)
STATE
%NSCLS 0 connection closed
%NSLSN 1 listening for RFC
%NSRFC 2 RFC in to listen
%NSRCL 3 CLS received after RFC
%NSRFS 4 RFC sent
%NSOPN 5 open
%NSRFN 6 RFNM wait on output
%NSCLW 7 CLS sent, waiting for matching CLS
%NSCLI 10 CLS received data available to input
%NSINP 11 input available
REASON FOR CLS (state 0)
%NCNTO 0 never opened connection (not .OPEN)
%NCUSR 1 CLS by user (.CLOSE)
%NCFRN 2 CLS by foreign host
%NCRST 3 RST (reset) from foreign host (dead)
%NCDED 4 host dead (see also NETHST call)
%NCINC 5 incomplete transmission (see NETHST)
%NCBYT 6 byte size mismatch
%NCNCP 7 local NCP went down, breaking connection
%NCRFS 10 connection refused by foreign host
SKIPS: No skip
FAILURE RETURNS: None
SIDE EFFECTS: None
EXAMPLE:
MOVE ac, [ch,,blk]
.RCHST ac,
.
.
BLK: BLOCK 7
Equivalent:
.CALL RCHST
arg 1 network channel number
val 1 'NET,,0
val 2 local socket number
val 3 foreign socket number
val 4 4.9 interrupt received
2.1-2.9 byte size
1.1-1.9 host number
val 5 LH IMP Down time/reason
RH Socket state (%NSxxx)
val 6 Open mode
val 7 RH Close reason (%NCxxx)
val 8 RH Number of bits____ available
(input data available or output buffer room)
.CALL WHYINT
arg 1 network channel number
val 1 %WYNET
val 2 Socket state (%NSxxx)
val 3 Number of bytes_____ available
(input data available or output buffer room)
val 4 Close reason (%NSxxx)
This call is usually used to respond to a second-word interrupt
from a network channel.
CALL: .STATUS
FUNCTION: Reads status of Network channel
ARGUMENT TEMPLATE:
Channel number in AC field of .STATUS instruction
RETURNS: Status of word in location addressed by
@ E (X) fields of .STATUS instruction
SKIPS: No skip
FAILURE RETURNS: None
SIDE EFFECTS: None
EXAMPLE:
.STATUS ch, statwd
Statwd: BLOCK 1
FORMAT OF STATUS WORD
_________________________________
| | |
| ERROR CODE | SS0026 |
|_______________|_______________|
ERROR CODE
if IOC (I/O channel error) or OPEN failure,
codes will be stored here.
SS
state (byte 140600), same as that given for
.RCHST -- see list of states
26
code for Network device
Equivalent:
.CALL STATUS
arg 1 channel number
val 1 status word as above
CALL: .NETACC
FUNCTION: NETwork ACcepts Connection (after LISTEN type
.OPEN)
(to REJECT, do a .CLOSE)
ARGUMENT TEMPLATE:
Channel number in AC field of .NETACC instruction
RETURNS: Nothing
SKIPS: Skips on success
FAILURE RETURNS:
Not skip --not in state 2 (RFC received to LISTEN)
SIDE EFFECTS: Sends matching RFC (and "allocate" if input)
EXAMPLE:
.NETACC ch,
JRST error
CALL: .NETS
FUNCTION: NET Send buffer now
(Buffer is normally sent when "full" or after
1/2 second of first activity)
ARGUMENT TEMPLATE:
Channel number in AC field .NETS of instruction
RETURNS: Nothing
SKIPS: No skip
FAILURE RETURNS:
IOC (I/O channel error)
Code 1, if not SEND (write) channel
SIDE EFFECTS: Buffer is queued to be sent immediately
EXAMPLE:
.NETS ch,
CALL: .CALL FORCE
arg 1 channel number
Equivalent to .NETS (see above)
CALL: .CALL FLUSH
arg 1 channel number
Does FORCE then waits for all buffered data to be sent
and for the final RFNM to come back.
CALL: .CLOSE
FUNCTION: CLOSEs channel and returns immediately
ARGUMENT TEMPLATE:
Channel number in AC field of .CLOSE instruction
RETURNS: None
SKIPS: No skip
FAILURE RETURNS: None
EXAMPLE:
.CLOSE ch,
Equivalent:
.CALL CLOSE
arg 1 channel number
CALL: .CALL NETBLK
FUNCTION: Hang until connection is not in specified
state or until time out
ARGUMENT TEMPLATE:
Standard .CALL arguments
1. channel number
2. state -- returns when not in this state
3. (optional) time -- number of 30ths of second
to wait or -- (time since system up) in 30ths
of second
RETURNS: 1. (optional) state -- new state
2. (optional) time -- time left after state
change
SKIPS: Skips on success
FAILURE RETURNS:
Not skip and
OPEN code 14 -- channel number not <20
-- channel not Network device
SIDE EFFECTS: None
EXAMPLE:
.CALL netblk
JRST error
.
.
Netblk: SETZ
SIXBIT /NETBLK/
channel
state
time
2000,,newstate
402000,,timeleft
Channel: ch
State: <-wait for this state to be left>-
Time: <-30ths of second to wait>-
Newstate: BLOCK 1
Timeleft: BLOCK 1
The time argument is clobbered in the same way that
.SLEEP clobbers its AC; unless it is immediate. In that
case, the time out will be restarted if the job is pclsred.
CALL: .RESET
FUNCTION: Used to RESET interrupt bit
(INR/INS from Network)
ARGUMENT TEMPLATE:
Channel number in AC field of .RESET instruction
RETURNS: Nothing
SKIPS: No skip
FAILURE RETURNS: None
SIDE EFFECTS: Clears the Network interrupt bit (see .RCHST,
bit 4.9 of word 3)
EXAMPLE:
.RESET ch,
Equivalent:
.CALL RESET
arg 1 channel number
CALL: .NETINT
FUNCTION: Sends Network INR/INS control message for
link corresponding to channel. (TELNET protocol also
demands a "data mark" to be inserted in the stream)
ARGUMENT TEMPLATE:
Channel number in AC field of .NETINT instruction
RETURNS: Nothing
SKIPS: Skip if success
No skip if Network down or not a Network
channel
FAILURE RETURNS:
I/O Channel error Interrupt, NET went down
Code 1
SIDE EFFECTS: Sends NET INR/INS control message
EXAMPLE:
.NETINT ch,
JRST fail
CALL: .GETSYS areas
NCPHTB
NCPPQ
NCPSM
FUNCTION: Get socket map
host table
pending queue
ARGUMENT TEMPLATE:
Name of first of 2 consecutive accumulators in AC
field of .GETSYS instruction
ac/ -<-length>-,,<-address>- ;CPTR to block to store
ac+1/ SIXBIT/<-name>-/ ;sixbit name of area
desired
RETURNS: Block of desired information
SKIPS: Skips on success
FAILURE RETURNS:
No skip -- area name not known in system -- not
enough memory
(ac+1 zeroes)
(ac gets <-lng,,> for number of words needed)
SIDE EFFECTS: None
EXAMPLE 1:
;This can be used to find out how much storage is
needed for a .GETSYS block
HRROI ac,temp
MOVE ac+1, [SIXBIT/NCPSM/]
.GETSYS ac,
HLRES ac ;here ac contains
lng,,temp
MOVNS ac ;now ac contains
number of words
needed
CALL FREE (ac)
EXAMPLE 2:
MOVE ac, [-lng,,blk]
MOVE ac+1 [SIXBIT /NCPSM/]
or NCPHTB or NCPPQ
.GETSYS ac,
JRST error
.
.
BLK: BLOCK lng
NCPHTB area
Length -- 400 (8) words (256(10))
Format -- one word per host number
(word(i) is data for host.number (i))
Each word has info packed --
|1| | 2 | 9 | 18
______________________________________________
|R| | | | | |
|F| | | | | |
|N|unused|RST| CTL TIME|00| HOST DEAD STATUS |
|M| | | | | |
|_|______|___|_________|__|__________________|
RFNM 0-control link open
1-waiting for RFNM on control link
RST 0-host down or not tried
1-sent RST to see if up
2-got RRP, connections may be opened
CTL TIME 9
Last time (1/30 sec module 2 )
message sent to this host on control link (0)
HOST DEAD STATUS
Last HOST DEAD STATUS from this host's IMP
(See RFC 611)
(If data for a single host is desired, use the NETHST call)
HOST DEAD STATUS in right half
Bits 20-31 (byte pointer [041400,,x])
give the time of the Host's coming back up,
bit-coded as follows:
Bits 20-22 (byte pointer [150300,,x]
the day of the week the Host is coming back up
Monday is day 0 and Sunday is day 6
Bits 23-27 (byte pointer [100500,,x])
the hour of the day, from hour 0 to hour 23,
that the Host is coming back up
Bits 28-31 (byte pointer [040400,,x])
the five minute interval, from 0 to 11, in the
hour that the Host is coming back up
All three of the above are specified in Universal Time
(i.e., G.M.T.). The Host may indicate that it will be
coming back up more than a week away by setting bits 20-31
all to ones (7777). Setting all bits 20-30 to one and bit
31 to zero (20-31 = 7776) means it is unknown when the Host
is coming back up.
Bits 32-35 have the follwing meanings:
Value Meaning
----- -------
0 The destination Host is not communicating with the
network -- the destination IMP has no information
about the cause. Note that this is the message most
likely to occur if the destination IMP has gone down
since the destination Host went down.
1 The destination Host is not communicating with the
network -- it took its ready-line down without saying
why.
2 The destination Host is not communicating with the
network -- the Host was tardy in taking traffic from
the network and the network had to declare the Host
down.
3 The destination Host does not exist to the knowledge
of the NCC.
4 Currently unused.
5 The destination Host is down for scheduled P.M.
6 The destination Host is down for scheduled hardware
work.
7 The destination Host is down for scheduled software
work.
8 The destination Host is down for emergency restart.
9 The destination Host is down because of power outage.
10 The destination Host is stopped at a software
breakpoint.
11 The destination Host is down because of a hardware
failure.
12-15 Currently Unused.
When the value of this 4-bit field is 0,1,2, or 3, bits 20-31
will have the "unknown" indication.
NCPPQ area -- pending queue of RFC's
Length -- variable 3+4*n where n is currently 40 (8) but
may change
Format --
word 0 -- relocation word, tells location in system
core where first slot begins
word 1 -- pointer to first queue entry
word 2 thru 4*n+1 -- 4 word slot for queue or -1 if
last one on queue
(0) -- pointer to next one (must un-relocate,
using word 0
(1) -- local socket number
(2) -- foreign socket number
(3) -- sign bit 0 = STR 1 = RTS
low order 8 bits (byte pointer [001000,,X])
link number if RTS
byte size if STR
next 8 bits (byte pointer [101000,,x])
foreign Host number
Example of unrelocating for the NCPPQ area.
;Let ac,ac+1 and b be accumulators
MOVE ac, [-lng,,blk]
MOVE ac+1, [SIXBIT /NCPPQ/]
GETSYS ac,
JRST error
MOVEI ac, blk
MOVN b,(ac) ;-system address
loop: ADD ac,b ;ac now points to
;first queue entry
;0(ac) is next pointer word
;1(ac) is local socket word
;2(ac) is foreign socket word
;3(ac) is Host -- lind/byte word
MOVE ac,0(ac) ;get next
JUMPGE ac,loop ;loop if not last one
NCPSM area
Length -- 1+13.*20. = 261(10) or 405(8)
there are 13 (or more) blocks each of length
IMPSTL (an assebly parameter, currintly 20(n))
Format --
word 0 -- contains IMPSTL, the number of words
in each block
word 1 -- begins first block -- the blocks are:
IMSOC1: REPEAT IMPSTL,0 ; 0 => FREE
; 4.9 = 1 => SOCKET IN USE
; 4.8 = 1 => CHNL TRYING TO BE CLOSED
; 3.1-4.7 MASK FOR INTERRUPT BIT (LSH 1 CHNL#)
; RH = USER INDEX
IMSOC2: BLOCK IMPSTL ; 1.1-4.5 = LOCAL SOCKET NUMBER
; 4.6-4.9 0 (MAKES COMPARISONS EASIER)
IMSOC3: BLOCK IMPSTL ; 1.1-4.5 = FOREIGN SOCKET NUMBER
; 4.6-4.9 = 0
IMSOC4: BLOCK IMPSTL ; RH = SOCKET STATE
; 3.1-3.8 = LINK NUMBER
; 3.9-4.7 = FOREIGN HOST NUMBER
; 4.8 = SET BY RCV CLS - MAKES MATCH USING IMSCHD FAIL
; 4.9 = SEND THIS BUFFER NOW
IMSOC5: BLOCK IMPSTL ; 1.1-1.8 = CONNECTION BYTE SIZE
; 2.1-2.9 = CLOSE REASON
; 3.1-3.8 = USER BYTE SIZE
; 3.9 => ASCII MODE - 7 BIT
; 4.1 => ASCII MODE - 8 BIT
; 4.2 => 1 BIT BYTES
; 4.3 => NET INTERRUPT (INR/INS) RECEIVED
; 4.4 => HAVE BEGUN CLOSE TIMEOUT
; 4.5 => CLOSED WHILE IN RFNM WAIT, EXPECT ANOTHER RFNM
; 4.9 => TRANSFER IN 32 BIT MODE
IMSOC6: BLOCK IMPSTL ; RH => BUFFER ADDRESS
; 4.9 => LOCKED BY CORE JOB
; 4.8 => ACTIVE AT PI LEVEL
; 4.7 => INPUT OCCURRED WHILE BUFFER LOCKED
; 3.1-3.8 => IOBFT INDEX, OR 377 IF BIG BUFFER
IMSOC7: BLOCK IMPSTL ; BIT ALLOCATION
IMSOC8: BLOCK IMPSTL ; MESSAGE ALLOCATION
IMSC7I: BLOCK IMPSTL ; AMOUNT TO INCREASE BIT ALLOCATION BY IN NEXT ALL MSG
IMSC8I: BLOCK IMPSTL ; AMOUNT TO INCREASE MESSAGE ALLOCATION BY " " " "
IMSOCT: BLOCK IMPSTL ; TIME WHEN FIRST MESS PUT INTO BUF
; (DURING INPUT HAS NUMBER OF DATA BYTES LEFT IN MSG)
; (DURING CLOSE HAS TIME TIMEOUT STARTED)
IMSMPP: BLOCK IMPSTL ; MAIN PROGRAM POINTER, ILDB OR IDPB FOR NEXT BYTE
IMSMPC: BLOCK IMPSTL ; MAIN PROGRAM COUNTER, FOR OUTPUT HAS ROOM LEFT
; IN BUFFER IN BYTES. FOR INPUT HAS TOTAL NUMBER
; OF DATA BYTES IN THE BUFFER.
IMSPIP: BLOCK IMPSTL ; INTERRUPT LEVEL POINTER. FOR OUTPUT ILDB GETS
; FIRST BYTE OF NEXT MESSAGE OUT. FOR INPUT RH
; HAS ADDRESS OF HEADER WORD OF NEXT MESSAGE IN.
IMSBFE: BLOCK IMPSTL ; BYTE POINTER TO LAST BYTE IN BUFFER.
CALL: .IOT
FUNCTION: Transfer data in or out over Network
ARGUMENT TEMPLATE:
Channel number in AC field of .IOT in struction
<-word>- or pointer to block
RETURNS: None (unit output mode)
Datum (unit input mode)
Updated pointer (block mode)
SKIPS: No skip
FAILURE RETURNS:
I/O Channel error INTERRUPT
Code 1 -- Network went down
Code 8 -- Attempted output mode IOT when not in
State 5 (open) or State 6 (RFNM wait)
Or attempted input IOT when in bad state
or when closed other than by foreign host.
End of file is sensed when input is done from
a socket closed by the foreign host. In unit
image mode this gives I/O channel error code 2.
SIDE EFFECTS:
Output -- data buffered to be sent
Input -- data copied from buffer ALLOCATE sent if
buffer empty (enough)
EXAMPLE: .IOT ch, foo
In image block mode, one byte per word is transferred,
right-justified.
In ascii block mode, five bytes per word are transferred,
or four bytes per word (8-bit) if mode bit 1.6 was on in
the OPEN.

310
doc/sysdoc/tv.100 Executable file
View File

@@ -0,0 +1,310 @@
A slightly revised TV-11 program is up and running.
There are the following features/changes:
SHIFT and SHIFT-LOCK no longer XOR. The general reaction
was against that feature, so it was removed.
[ESC]D Buzzes the ninth-floor door for three seconds and
then flashes your screen. It works for free consoles
as well.
[ESC]Q Generates a hardcopy, as before, but the timeout is
sixteen seconds, avoiding garbage output.
[ESC]L Clears your screen.
NOTE: This is the same command as [ESC]I, which
is retained for old times' sake for the
moment, but will be garbage-collected
soon.
_______________________________________________________________
A. THE WHO-LINE.
The who-line is a line that appears at the bottom of the screen
on a TV terminal, describing the status of either the system as
a whole, or a particular job. In the former case, it is said
that the system who-line is being displayed; in the latter, the
user who-line. The information is updated every 5 seconds. The
who-line may be turned on or off, and various modes may be
selected, under either user or program control.
1. WHAT APPEARS IN THE WHO-LINE.
a. The User Who-line.
The user who-line begins with system status information:
the version number of ITS, the time of day and the date.
Then comes information on the job that is selected for who-line
display: the job number, the uname, jname and sname,
a "status" that says what the job is doing,
the percentage of the system's time that the job is running,
its total run time so far, and its core size in K.
An example of a user who-line is:
12/31/74 21:21:30 20 RMS NT .INFO. TTY 5% 0:03:09.2 24K RANDOM CRUFT
^time. ^uname. ^sname. ^% runtime. ^core size.
^date. ^job #. ^jname. ^status. ^job runtime. ^user-specified stuff.
1: The Who-line Status.
STOP means that the job has been stopped (presumably by its
superior). This will be the case for jobs that have
been ^Z'd.
RUN for jobs that are running in user mode - that is,
neither stopped nor executing a system call.
PAGE means that the job is waiting to swap a page in.
<device>
means that the job is executing an IOT (or SIOT) on that device.
Appended to the name of the device may be the following
characters:
I input.
O output.
B block mode.
S string mode.
For example, DSKBI means block mode input from the disk.
<system call name>
(for example, "OPEN", "CLOSE").
means that the job is executing the system call named.
If the job is currently executing a system call (which implies
that the status is not RUN or STOP), a "+" will
appear in front of the status if the job is actually running, as
opposed to waiting (for buffer space, etc).
Thus, "DSKBI" indicates that the job is waiting for a disk
transfer to take place, while "+DSKBI" indicates that it is
copying information out of a system disk buffer.
The user-specified part of the who-line is controlled by the
.WHO1, .WHO2 and .WHO3 variables of the job described by the
who-line. Those variables exist so that the program running can
show whatever internal status information it thinks the user might
want to know - what page of input is being processed, for example.
See the description of those variables in ITS USETS for details of
how to use them in a program.
b. The System Who-line.
The items in the system who-line are as follows:
ITS XXX MM/DD/YY HH:MM:SS USERS RNBL/TJOB SWAPB PAGEW RCORE/UCORE FCORE
XXX ITS version #
MM/DD/YY today's date
HH:MM:SS time of day
USERS number of users logged in
RNBL number of runnable jobs
TJOB total number of ITS jobs
SWAPB number of swap blocked jobs
PAGEW number of jobs waiting for pages
RCORE number of pages belonging to runnable jobs
UCORE total number of pages in the system.
FCORE number of user pages there is room for
in real core at one time.
In addition, if ITS is being debugged, the system who-line
will mention that fact.
2. USER CONTROL OF WHO-LINES.
Currently, who-line control uses the [ESC]W command, interpreted
directly by the PDP11. When a command is given, it is not really
processed until the next time the who-lines are updated. The
issuing of a command triggers such updating immediately, even
if the normal time for updating has not arrived, but there may
be a delay nevertheless. In that case, a second command given
before the updating is done will overwrite the first.
The options are:
[ESC]W turns off the who-line.
[ESC]1W selects the user who-line, migrating with the
ownership of the tty. That is, each time the
who-line is updated, it will describe whichever
job has the tty at that moment.
This is the default status.
[ESC]2W freezes the who-line on whatever job was last
shown. If you are about to ^Z - ^P a job but
wish the who-line to continue to show that job
instead of following the tty to its superior,
this is the thing to do. The who-line remains
frozen until the next time it is explicitly
changed. If the job selected disappears, strange
things may be displayed.
[ESC]3W moves the who-line to a different job with
the same uname as the one previously shown.
Repeated use of this command will cycle through
all the jobs with your uname. The who-line is
left frozen on whichever job is reached.
[ESC]4W moves similarly but in the other direction. That
is, it will move back to the job that [ESC]3W
left.
[ESC]5W selects the system who-line.
[ESC]<n>U selects the user wholine, for job number <n>.
The job need not be part of your tree.
3. PROGRAM CONTROL OF WHO-LINES.
a. The Variables.
Two variables, WHMODE and WHJOB, contain the information
about which mode of who-line display is selected.
WHMODE is interpreted as follows:
-1 no who-line display.
0 user who-line, migrating with tty.
1 user who-line, frozen on a particular job
whose job number is in WHJOB.
4 system who-line.
(2 and 3 are transitory states that occur while [ESC]3W or
[ESC]4W is waiting to be processed. [ESC]W actually works
by putting its argument plus 1 into WHMODE).
b. System Calls.
The WHOLIN symbolic system call is used for reading and
writing the two variables WHMODE and WHJOB. Its first
argument specifies the tty to be used. The second and third
arguments are optional; if present, they will be used to set
WHMODE and WHJOB. In any case, two values are available:
the previous values of WHMODE and WHJOB.
If only one argument is given, the tty may be specified by
number, since it is not being modified. If two or three args
are given, the tty must be specified by a channel.
If the tty specified is not a TV, the call will fail with a
"wrong type device" error.
For example, to put the old values in FOO and FOO1, and
freeze the who-line on the job whose number is in BAR1:
.CALL [ SETZ
'WHOLIN
1000,,TYIC ;IMMEDIATE TTY CHANNEL ARGUMENT.
1000,,1 ;NEW WHMODE = FREEZE ON JOB.
BAR1 ;JOB TO LOOK AT.
2000,,FOO ;STORE OLD WHMODE.
402000,,FOO1] ;STORE OLD WHJOB.
.VALUE
...
c. Use of the TCTYP Program.
The TCTYP program when asked to describe a tty fully, or when
a tty's WHMODE is not -1, will print out "WHOLINE=" followed by
one plus the value of WHMODE (in other words, the argument to
[ESC]W needed to put the tty in the state it is in). The command
"WHOLINE" is also available; it takes an argument and acts like
[ESC]W, except that 1) it may be put in init files and valret
strings, while [ESC]W cannot, and 2) giving the WHOLINE command
an argument of 3 or 4 does not produce useful results.
Thus, if you like having a who-line,
:TCTYP WHOLINE 1
in your init file will give you one automatically.
B. FEATURES FOR PROCESSING WHAT IS ON A TV SCREEN.
What is sent to an ordinary terminal is unknowable to the
system unless specially remembered. That is not true
of TV terminals. Some standard facilities for processing
the contents of TV screens appear below. Of course, any
program may examine TV screens simply by mapping their
pages.
1. THE HARD COPY PRINTER.
There exists a device for making a printed reproduction of
whatever appears on a TV screen. To use it, type [ESC]Q,
which causes one copy to be made immediately. If the device
is in use, the screen will flash and no action will be taken.
The process lasts 16 seconds; nothing prevents the screen from
changing during that period, and if such a thing happens the
results will be interesting. When the copy is finished, the
screen will flash. Thus [ESC]Q always flashes the screen,
but faster if you're losing. If an infix argument is given as
for [ESC]S (see below), then the specified video input is copied.
This command can be used even on non-logged-in keyboards.
2. RECORDINGS.
The system program RECORD will make an ascii file out of
whatever is on the TV screen. To use it, just type
RECORD^K at DDT. The file is called RECORD >
and goes on your default directory (the MSNAME).
Other more sophisticated programs for handling TV bit maps
may be found documented in AI:.INFO.;TVXGP INFO.
3. SPYING.
When using a TV terminal, it is possible to spy on any other
TV terminal. This operates by routing a different video memory
through the video switch to your screen. Doing this does not
affect your programs in any way - their output continues to
be placed in your own video buffer and will be visible when
you stop spying. Also, spying does not affect the handling
of input in any way.
These commands can be used even on free keyboards.
[ESC]<n>S on free keyboards, and [ESC]F on keyboards that are in use,
will time out after 40 seconds and an automatic [ESC]S will be done
to make the screen show its default picture once again.
Any character typed will make that happen prematurely.
The commands are:
[ESC]<n>S begins spying. The number <n> should be the number
of the terminal to spy on; thus, [ESC]64S spies
on TTY T64. If the specified tty is not in use,
the command is a no-op.
<n> may also be 200 plus the number of a video buffer.
This makes it possible to spy on a screen that nobody
is currently using.
<n> may also be a video switch input number,
for those of you who are hardware hackers.
[ESC]S stops spying. You are again viewing your own
video buffer.
[ESC]F spies on the video buffer used for logged-out consoles
(this is the one with the useful information from
the NAME dragon).
C. OTHER TV FEATURES.
1. COMPLEMENTING THE SCREEN.
The last PDP-10 word of every display memory is used to hold
various information on how the contents of the memory should
be modified on their way to the screen. The 200000 bit of the
word controls complementation of the screen; if the bit is
on the screen appears black on white. This bit may be complemented
by the user with the command [ESC]C. Programs may, of course,
change the bit easily by accessing the display pages.
2. CLEARING THE SCREEN COMPLETELY.
[ESC]L is guaranteed to clear every bit of the display memory,
and also reset the scroll-register (don't worry if you don't
understand that). ^L usually does a good enough job, so this
command is hardly ever necessary. If ^L doesn't clear the
screen (because a program has turned it off), ^_L will clear it.
3. THE REPEAT KEY.
[ESC]R is the "repeat key"; it causes the previous input
character to be sent to the PDP-10 8 times a second, forever,
or until a character is typed on the keyboard (escape commands
not included). The character that stops the repeat will be
ignored as input, unless it is CALL.
[ESC]<n>R, where <n> is an OCTAL number, will repeat the
previous input character <n> times (or until stopped by
the typing of a character). <n> can't be more that 177 (octal).
4.

1405
doc/sysdoc/usets.119 Executable file

File diff suppressed because it is too large Load Diff

823
doc/sysdoc/usr.102 Executable file
View File

@@ -0,0 +1,823 @@
JOBS IN ITS
@. ABSTRACT.
In ITS, a "job" is an entity that consists mainly of memory to hold
a program, registers to run it with, and I/O channels for it to do
I/O on through the system. Whenever a program is
running, it must be running "in" some job. Jobs are structured
into trees; the root of a tree is a "top-level" job, and for any
job, the job one step closer to the root is the first job's superior;
the first job is one of its inferiors. Normally, each user has
one tree of jobs, but he may also have a few other secondary trees.
Jobs may read anything associated with any job, but usually may write
only their direct inferiors.
TABLE OF CONTENTS
A. OVERVIEW OF JOBS.
B. CREATING AND DELETING INFERIORS, AND OTHER METHODS OF CHANGING THE
0. OPENING THE USR: DEVICE - A BASIC TOOL.
1. CREATION
2. DELETION
3. DISOWNING
4. REOWNING
5. DETACHING
6. ATTACHING
7. LOGGING IN
8. LOGGING OUT AND GUNNING
C. CONTROL OF INFERIORS.
1. READING AND WRITING
2. SHARING MEMORY BETWEEN JOBS
3. LOADING
a. Resetting
4. DUMPING
a. Pure dumping
b. Impure dumping
5. STARTING AND STOPPING
6. HANDLING INTERRUPTS
7. DEBUGGING CONTROLS.
8. TTY PASSING
D. SYSTEM JOBS AND WHAT THEY DO
1. THE SYSTEM JOB.
2. THE CORE JOB.
3. DEMON JOBS.
A. OVERVIEW OF JOBS.
Each ITS job has an address space, the slots of which may be filled
with various types of memory, perhaps shared with other jobs; its own
set of accumulators (copied temporarily into the real ones when the
job is running); a program counter (PC); sixteen I/O channels, each of
which may be used to handle a device or file; system "user variables"
with which the program in the job may communicate with the system;
and other variables used by the system in scheduling
or swapping the job, or as temporaries for system call routines.
The word "user" has two meanings on ITS: one is the human or other being
using a terminal; the other is an individual "user job". In specific
contexts either "job" or "user" sounds better for their common meaning.
A "program", however, is a more abstract entity; the same program may
be running in several jobs (but using different files, etc. in each).
Each job is identified by two names, the UNAME and the JNAME, each of
which is up to six SIXBIT characters, left justified in a PDP-10 word.
They are available in the .UNAME and .JNAME user variables of the job.
These two names uniquely identify the job.
All the jobs in a tree must have the same uname. Two trees may have
the same uname; that usually means that they really correspond to the
same user.
Each job is also uniquely identified by its "job number" (or
"user number"), which is a small positive number. This number
is the usual way to specify a job in a system call. A job may find
out its own number by reading its .UIND user variable; its superior's
is in its own .SUPPRO user variable. The term "user index"
may mean, loosely, the job number, but more strictly it means the
job number times LUBLK, the length of the system's per-job data block
(the "user variable block"). Supported communications paths
between the user and the system use the job number, not the user index
itself, even if the term "user index" is used.
A job has several "user variables" which are really variables in the
system that pertain to it, and are readable by that job or others
using the .USET and .SUSET UUO's (see ITS UUOS). Each user variable
has a name, which starts with ".". User variables can be opened in
DDT just like memory locations, although what DDT does to access them
is a .USET. Some user variables, such as .UIND, .SUPPRO, .UNAME and
.JNAME mentioned above, exist solely to be read by programs. Others
also allow the program to tell the system how to treat it; examples
are .OPTION, which contains bits that enable various system features,
and .MASK, which is used to enable user interrupts (see ITS INTRUP).
A complete list of user variables and what they contain is in the
file ITS USETS.
When a user connects to ITS by typing ^Z or CALL on a terminal, he is
supplied with a single top-level job using that terminal, running the
program "DDT" (on DM, "MONIT" is used instead). The jname of that
job is always "HACTRN" (pronounced "hack-tran"),
and the job is called "a HACTRN". The uname
will be three backarrows followed by three digits, identifying the tree
as non-logged-in. "Logging in" is nothing other than altering the uname
of the hactrn to a more meaningful name. It makes little direct
difference.
DDT and MONIT both provide facilities for creating other jobs for the
user, loading programs into them, and running them. There are no user
commands per se for controlling jobs built into ITS; instead, the
user gives commands to DDT or MONIT telling them to execute the system
calls to control his other jobs.
The two main types of job trees are the console-controlled trees and
the non-console-controlled (or "disconsolate") trees. A console
controlled tree has one terminal which is "in use as a console" by
the whole tree. All the jobs in the tree can refer to that terminal as
device TTY:. The number of that terminal can be found in the .CNSL
variable of any job of the tree.
At any time, only one of the jobs in the tree has
permission to do I/O to the console; that job is said to "own"
the console. Ownership is transferred by means of .ATTY and .DTTY
UUO's executed by jobs in the tree (see ITS TTY). If ^Z (or CALL on
TV's) is typed on a console, the job that owns it gets a fatal
interrupt. The jobs may also have other terminals open "as devices",
but those can be in use only by a single job, not the whole tree.
The console-controlled trees are usually the ones with hactrn's at the
top.
Disconsolate trees do not have any console, but in all other respects
bahave just like console-controlled trees. They may or may not be
"disowned". If they are, they get worse treatment from the scheduler
and swapper, and also may be more conveniently "reowned" (made into a
subtree of another tree - see below). Usually only system demons and
job-device handlers are disconsolate non-disowned trees.
Job-devices will have a .CNSL equal to that of the tree of the
job using the job-device. Other disconsolate jobs will have a .CNSL
of -1 if they are scheduled as part of the system, or -2 if scheduled
as disowned jobs.
Jobs often refer to each other using a device, the "USR" device. A job
may be opened on the USR device by specifying its uname and jname as the
opened filenames. It is then possible to examine or deposit the job's
memory or user variables, etc. This is why DDT, when it starts up,
mentions its uname and jname by saying "USR:<uname> <jname>".
The USR device should not be confused
with the JOB device, which is a mechanism for creating software devices
which enables the system calls that manipulate the device to be
simulated and handled by a user program, the job-device handler program
(See ITS JOBDEV).
The remainder of this file is devoted to desribing the ITS system calls
with which jobs may create, delete, sense and control other jobs.
B. CREATING AND DELETING INFERIORS, AND OTHER METHODS OF CHANGING THE
TREE STRUCTURE OF JOBS.
0. OPENING THE USR: DEVICE - A BASIC TOOL.
Unfortunately, many different things are done by opening the
USR device in different ways in different situations. They
include creation of inferiors, reowning disowned jobs, selection
of existing jobs (inferiors or not), and testing for the existence
of a job. Opening USR is the ONLY way to do those things. What's
more, a job's memory cannot be read or written without having a USR
channel open in the appropriate direction, and a job's user variables
cannot be read or written without at least one USR channel open in
either direction. Thus, opening USR: is very important. It is intended
that this mechanism will be made more rational in the future.
This section will describe what opening the USR device will do,
organised by how it is done. Later sections will say what
to do to achieve a specific goal.
By convention, "USRI" and "USRO" are the canonical names in MIDAS
programs for the I/O channels used for opening the USR device for
input and output, respectively. Their use in an inferior-handling
program is a sort of comment.
A USR: open always specifies two filenames. Normally they are
the uname and jname of the job to be opened. However, 0 may
be used as the first filename to specify your own uname.
If the second filename is 0, then the first is not really a
name but a job spec; this crock makes it possible to open a
job known only by its number.
A USR: open must also ask for either block mode or unit mode.
Right now SIOT on unit mode USR channels is not as efficient as
IOT on block mode channels, so it is usually better to open in
block mode. In any case, this choice is orthogonal to everything
else.
All USR: opens should specify image mode. Ascii mode doesn't now
exist for the USR device, and if you ask for it you will get image
mode instead, so for compatibility with the future you should ask
for image mode.
There are four things specified in each USR open that affect the
actions taken in important ways. They are the two filenames,
the direction, and the device-dependent bit 1.4 of the open-mode,
known here (and inside ITS) as UBPFJ.
If UBPFJ is set, the open may be for reading only, and will fail with
code 4 if the job specified by the uname and jname does not exist.
If the job does exist, it will be opened as a "foreign job", which
means that the opening job may not modify it at all using the
channel opened in this way. Also, the process of opening the job
with UBPFJ is guaranteed not to alter it. This style of open is
good for asking whether a job exists with particular names.
Without UBPFJ, if the open is for writing, then
if a job with the specified uname and jname exists and is the
inferior of the job doing the open, it will be opened for
writing, with no special side effects.
If a job with the specified names exists and can be reowned
(it is a top-level disowned job), it will be reowned, and
opened for writing. Reowning may change its uname or jname,
so whenever an open might reown a job the program should
read back the uname and jname of the opened job just in case.
If no job with the specified names exists, then an attempt is
made to create an inferior by that name. If the specified
uname isn't the same as yours, that is impossible, and the open
fails with code 20. If you already have the maximum number of
inferiors, it fails with code 5. If there are no job slots available,
it fails with code 6. If the attempt succeeds, the new inferior
is opened for writing.
Otherwise (a job with the specified names exists, but isn't
an inferior of the running job already and can't be made one
by reowning it), the open fails with code 12.
Note that if an open for writing succeeds, you know the job that
is open is your inferior (thought it might not have been so before).
An open for reading, without UBPFJ, is like an open for writing
except that when the job exists but isn't an inferior and can't
be reowned, it will be opened as a foreign job (as if UBPFJ were 1).
To understand these possibilities better, think of the FOO$J command in
DDT, which means, essentially, "open the job named FOO". That command
will reselect a job named FOO if there is one; if not, it will create
one. If there is a job named FOO that isn't a direct inferior of DDT,
it will be selected, but will be unwriteable (DDT will type a "#"). If
there is a disowned job named FOO, it will be reowned (made into an
inferior of DDT), and DDT will type ":$REOWNED$").
There is no easy way to tell after the fact what has happened when
an open without UBPFJ has succeeded. You know you have an inferior,
if an open for writing succeeds,
but whether it is new, reowned or old is forgotten. If you care,
you should find out in advance what is going to happen by doing
an open with UBPFJ set. If it fails, you will get a newly created
inferior. If it succeeds, look at the .APRC and .SUPPRO user variables.
If both are negative, you have a top-level disowned job which
would be reowned. If .SUPPRO equals your .UIND variable, the
job is your inferior already. Otherwise, an open for writing
would fail, and an open for reading would open it as a foreign job.
Some information is still available after an open.
The job's .UPC variable will be nonzero iff the job has ever run
(because the user-mode bit, %PCUSR, will be 1).
If the job has been run, then it certainly wasn't just created.
Also, if the job's uname or jname was changed by the open, then
it must have been reowned.
1. CREATION
In order to create an inferior, one must choose a jname for it.
Its uname will have to be the same as its creator's, and together
the uname and jname must be unique among all jobs in existence.
An attempt to create an inferior looks just like an attempt to
open an existing job, so if the would-be creator is mistaken about
the uniqueness of the jname it may get confused (a way out of this
problem is described later).
Given a jname which isn't in use, an inferior of that name may be
created by simply opening the USR device with the uname and jname
as filenames, as in section 0. You should open a channel in each
direction (call the input channel USRI and the output channel USRO).
If you are unwilling to try to live with a foreign job, do the
output open first.
One way to make sure of getting a newly created job is to check
in advance that the names are not in use, by opening them with
UBPFJ (see section 0) before actually trying to create the job.
If the test open succeeds, close the channel again and
pick a new jname.
The new inferior will have 1K of zeroed unshared core,
and will not be running (its .USTP will be nonzero).
Then, if you wish to handle interrupts from the inferior,
read the inferior's interrupt bit, which may be found in
the inferior's .INTB variable, and remember it somewhere.
That is the bit .IFPIR on which YOU will be interrupted,
if the inferior gets a fatal interrupt.
2. DELETION
Inferiors do not need to remain open to continue to exist. Simply
closing the channels one is open on does not delete it; it is
merely hard to refer to until it is opened again. This is so
that it is possible to have many inferiors without tying up many
I/O channels. When it IS desired to delete an inferior, the
.UCLOSE uuo should be used:
.UCLOSE <channel>,
This uuo kills the inferior open on <channel>. All the channels
it is open on are closed. The uuo does not skip.
If a foreign job instead of an inferior is open, all the channels
in this job that it is open on are closed, but it is not killed.
If there isn't a job open on the specified channel, an ILOPR
interrupt happens.
3. DISOWNING
Disowning an inferior causes it to continue to exist, but no longer
as your inferior. This can be useful for two reasons:
1) you wish to log out but want the inferior to remain, or
2) you want the job to become someone else's inferior.
Disowning is done with the DISOWN system call, as follows:
.CALL [ SETZ ? 'DISOWN
401000,,<job spec>]
.VALUE
It fails if the specified job isn't an inferior of the executing one.
If it succeeds, the specified job and its inferiors become
a separate disowned tree, of which the specified job is the top.
All channels on which the running job had that job open are closed.
See the DISOWN symbolic system call for more details and features.
4. REOWNING
A top-level disowned job may be "reowned" (made one's inferior)
by opening it with bit 1.4 of the mode set to 0. The uname of
every job in the reowned tree will be changed to equal that of
the reowning job, if necessary. If as a result the uname/jname
pair of one of the reowned jobs is no longer unique, the jname
will be altered until the uname/jname pair is unique.
Another way to reown a job is to use the REOWN symbolic system
call. The job to be reowned should already be open on an I/O
channel as a foreign user; the REOWN will cause it to be open
as an inferior instead on the same channel. An example is:
.CALL [ SETZ ? SIXBIT/REOWN/ ? 401000,,USRI]
.VALUE
In DDT, selecting a job that may be reowned will always reown it.
DDT will type ":$REOWNED$" when that happens. If the uname or
jname changes, DDT will type the new names.
5. DETACHING
An entire tree may be made disowned, have its console taken
away from it, or both, with the DETACH system call. The goal might
be to free the console for other use, or to make the tree into
a subtree of another tree by reowning it.
6. ATTACHING
Attaching is the operation of connecting a terminal to a tree
as the tree's console. The simplest kind of attachment takes
a free console and a disowned tree and connects them. A top-level
console-controlled job may also attach one of its inferiors to
its console; this has the same effect as if it were to disown
the inferior, detach itself, and then attach the erstwhile inferior
to the now free console, except that it happens more smoothly.
DDT's :ATTACH command uses the second flavor of ATTACH. See the
ATTACH system call for more details.
7. LOGGING IN
When the system creates a top-level job (such as a HACTRN), its uname
will be three "_"'s followed by three unique digits. The job may
change its uname to one that gives more information to humans by
"logging in", which simply sets the uname. The job must not have any
inferiors at the time; the new uname must not start with "___" and
must not be in use. A logged-in job may not log in again, but it may
change its uname with a .SUSET of .UNAME.
Logging in is done with the LOGIN symbolic system call, as follows:
.CALL [ SETZ ? SIXBIT/LOGIN/
SETZ [<new uname in sixbit>]]
.VALUE
The system call takes an optional third argument which now should be
used only by network server telnet jobs. For them, its hould be the
sixbit string "HSTnnn", where nnn is the octal number of the foreign
host.
8. LOGGING OUT AND GUNNING
A top-level job may delete itself, and all its inferiors, by "loggin
out". This is done with the .LOGOUT UUO, as follows:
.LOGOUT
The UUO returns only if it fails (the job isn't top level); it does not
skip. Programs that do not normally run in top-level jobs might
nevertheless be run in disowned jobs sometimes, so they should always
try to log out before requesting another command string or trying to ask
DDT to kill them.
A job may force any top-level job to log out by "gunning" it, using the
.GUN UUO. The user index of the job to be gunned must be known. The
way to do it is:
MOVEI AC,<usr idx>
.GUN AC,
JRST LOSE ;FAILED - JOB DIDN'T EXIST OR WASN'T TOP LEVEL.
... ;SUCCEEDED.
Gunning should go on only between consenting adults.
C. CONTROL OF INFERIORS.
Jobs can control their inferiors by means of several special-purpose
system calls. The more specific of them are documented below under
their uses. One more general one is .USET, which allows the inferior's
"user variables" to be read or set. For example, when section C.5.
speaks of "setting the job's .USTP variable", a .USET is meant. The
way to set the .FOO variable with a .USET is this:
.USET <channel>,[.SFOO,,[<new value>]]
Thus, .USET <channel>,[.SUSTP,,[0]] will stop the job open on channel
<channel>.
.USET <channel>,[.RFOO,,TEMP] will read the value of the .FOO
variable into TEMP.
For a complete description of the available .USET variables, and more
features of .USET, see the file ITS .USETS.
1. READING AND WRITING
Reading or writing the contents of another job requires having the job
open on a USR device channel. It is done by .IOT'ing on that channel;
thus, reading requires an input channel and output requires an output
channel. Selection of the region to read or write is done by setting
the channel's access pointer with .ACCESS. At the moment, SIOT on unit
mode USR channels is not very efficient, so it is best to open a job in
block mode. That requires one extra instruction when transferring a
single word, which is a slight cost when compared with the ease of
transferring several words.
Note that ascii mode does not exist for the USR device - all channels
should be opened in image mode.
For example, to read the word at 500 into A, do
.ACCESS USRI,[500]
HRROI B,A
.IOT USRI,B
assuming that USRI is the USR input channel. This clobbers B.
To write A into the word at 500, do
.ACCESS USRO,[500]
HRROI B,A
.IOT USRO,B
assuming that USRO is the USR output channel. This clobbers B.
If a non-existent location in another job is read or written
with an IOT, an MPV interrupt results. The .MPVA variable
of the job doing the reading will point at the non-existent
page of the other job. (Actually, in ITS before version 1017,
when a non-existent page is written, the system may give an MPV,
or may do a .CORE on the inferior so that it has enough core
to make the IOT succeed. ITS version 1017 and up will
always MPV).
2. SHARING MEMORY BETWEEN JOBS
Another way to refer to the core of other jobs is to share
memory with them. The slots of a job's page map should be
understood to be pointers to pages; one page may be pointed
to independently by several slots in several jobs' page maps.
The CORBLK call can be used to copy other jobs' pointers to pages
into one's own job, resulting in shared memory. Of course,
the memory will not have the same address in both slots
unless that is specificaly arranged for.
Unfortunately, other jobs' accumulators cannot be referred to
via memory sharing, since they are not stored anywhere in
the job's memory even when the job isn't running.
3. LOADING
Loading a binary file into a job is not actually a fundamental
operation, since it could be done by a program that understood
the format of the binary file and deposited in appropriate
locations in the job being loaded. However, for convenience'
sake, the LOAD system call exists for loading a binary file
into an inferior, or into the running job itself. Both types
of ITS binary files may be loaded with LOAD; it is not necessary
to know which type of file is being loaded. Unfortunately, this
call works only for disk files. For other devices, the program
must do it the hard way. Code may be copied from DDT for that
purpose.
The LOAD system call takes two arguments: the job to be loaded,
and the file to load. The first is expressed by a job spec; the
second, by a channel number. For example,
.CALL [ SETZ ? SIXBIT /LOAD/
1000,,-1 ;into myself
401000,,DISKC] ;the file open on DISKC
.VALUE
The LOAD will leave the disk channel set up to read the file's
start instruction, which is a jump to the starting address, or
zero if there is no starting address. After that word in the
file should come the symbol table and another copy of the start
instruction; see DDT ORDER for their format.
Loading a PDUMP file (pure file) inserts pages into the job
as specified by the file. It does not alter the pages of the
job that the file has no data for. It also does not alter the
accumulators, even if page 0 is loaded. Loading an SBLK file
(impure file) alters only the words of the job that the file
specifies data for. The other words are NOT cleared. If data
are specified in a nonexistent page, fresh memory will be
put there, and also in all nonexistent pages below it in the
address space! Thus, if an impure dump is made of a job containing
nonzero data only at address 100000, the resulting file when
loaded will create core up through address 101777, even though
only the last page of that is actually being loaded. This
unfortunately cannot be changed, but often causes trouble. For
that reason (and many others), it is hoped that there will be
a new, more versatile binary format some day.
a. Resetting
Loading per se modifies only the locations that the binary file
specifies data for. It does NOT clear the rest of core. If you
want to do that, chances are that you really want to RESET the
inferior. To do that, use the .RESET UUO or the RESET symbolic system
call on an I/O channel with the inferior open.
RESETting a job deletes all of its core, provides it with a single
page of unshared writeable core, closes all the job's channels,
kills all of its inferiors, and re-initializes most of the job's
system variables. Most notably not cleared out are the job's
translation lists for filenames.
4. DUMPING
a. Pure dumping
b. Impure dumping
5. STARTING AND STOPPING
An inferior may be started (caused to run) by setting its .USTP
variable to zero. It will continue with whatever PC it has.
To set the PC, store the desired new PC in the .UPC variable.
An inferior may be stopped by setting the .USTP variable to
nonzero. The exact value deposited in .USTP will be forgotten
since it corresponds only to a single bit of real storage.
This is how the system stops a job which gets a fatal interrupt.
DDT has another way of stopping a job, which it uses in executing
the ^X command: it turns on bit %PIC.Z of the job's .PIRQC, causing
a fatal ^Z-typed interrupt in that job.
This not only makes the system set the job's .USTP, but causes
DDT's interrupt handler to find out about the stoppage of the
job and be properly faked out.
6. HANDLING INTERRUPTS
Every job has the ability to enable interrupts on several conditions
(see ITS INTRUP). Among those conditions is the occurrence of a fatal
error interrupt in an inferior. This is the mechanism that enables
a job to "return to DDT" deliberately - it simply causes a fatal
interrupt in itself. This is also how DDT knows when an illegal
instruction is executed by an inferior.
Whenever a job acquires an inferior (by creation or reowning), one
of the job's interrupt bits is assigned to that inferior. Each
inferior has its own interrupt bit. There are exactly eight
interrupt bits which can be used for that purpose, which is why a
job can have at most eight inferiors at a time. Those eight are
all located in the left half of the .IFPIR variable.
The superior should find out which interrupt bit was assigned by reading
the inferior's .INTB variable, in which that bit alone will be 1.
See ITS INTRUP for more details.
The two system calls .VALUE and .BREAK exist solely so that a job can
cause a fatal interrupt to signal its superior. DDT has standard
interpretations for those instructions; see .INFO.;DDT ORDER.
7. DEBUGGING CONTROLS.
These features exist to facilitate debugging. They work currently on
KA-10's only, though they will be extended to KL-10's eventually.
They are generally used and controlled only by the superior of the
job on which they are acting, to which they are generally transparent.
a: One-proceed.
If appropriate bits in a job's PC are set, that job will be
able to execute one more instruction and then will get a fatal
%PI1PR interrupt. This feature is used by DDT's "single step"
command (^N). Which bits to use depends on the processor type:
for KA's, %PC1PR is the right bit (it is an 18 bit quantity, to
be OR'ed into the flags); for KL's, %PS1PR is right. On any
machine, the symbol OIPBIT will be defined in the ITS symbol
table as either %PC1PR,, or %PS1PR,, , whichever is appropriate.
b: Address-stop (MAR).
The MAR feature makes it possible to trap all references to a
particular address. When the specified location is referred to
("the MAR is hit"), the inferior will get a fatal %PIMAR
interrupt, which may or may not allow the instruction that
tripped the MAR to finish. The MAR is turned off when it is
hit and must be turned on again explicitly or it will stay
off forever.
The MAR is controlled by the .MARA user variable. Its RH
contains the address to be traced. Its LH contains the control
code, which is 0 to turn the MAR off, 1 to trap instruction
fetches only, 2 to trap writes only, and 3 to trap all
references. There is also a variable .MARPC which, after
the MAR is hit, contains the address of the instruction that
hit it. In addition, the indirect bit will be set on KA's
if the instruction that hit the MAR was completed (on KL's,
the instruction is always aborted).
On KL's, after a MAR, the job's PC (.UPC) will have %PSINH
set, which will inhibit MAR hitting for one instruction
when the job is continued.
The job's PC in .UPC should NOT be used to locate the
instruction that hit the MAR, since if the instruction was
not aborted and was a jump, the PC will be the address
jumped to. Even if it wasn't a jump, it might have skipped.
c: .JPC - Last Jump Address.
The user variable .JPC always contains the address of the last
jump instruction executed in the job. It can be used, for
example, to trace a job backward from the point of failure by
putting in a breakpoint, examining the .JPC when the breakpoint
is hit, and running the program again with the breakpoint now
located at the previous jump, etc. Unfortunately, subroutine
calls (including user-trapping UUOs) alter the JPC, even though
the information is redundant for them, but returnable UUO's and
interrupts do not. For that reason, after a returnable UUO
or interrupt a program should always read .JPC before jumping
anywhere, for debugging purposes. The canonical names UUOJPC
and INTJPC exist for the locations .JPC is saved in. Also,
error-handling uuos used by the program should be returnable
uuos rather than direct user-trapping uuos, so that the JPC
will be meaningful. The vectored interrupt mechanism has the
ability to store .JPC automatically on each interrupt (see
ITS INTRUP).
8. TTY PASSING
For now, see under .ATTY and .DTTY in ITS TTY.
D. SYSTEM JOBS AND WHAT THEY DO
There are two jobs built into the system, that run in exec mode
and perform housekeeping tasks; they are the system job and
the core job. There are also various "demon" jobs that exist
at times which, though receiving no special treatment from the
system, may be regarded as part of it in that they provide a
system-wide service.
1. THE SYSTEM JOB.
This job, whose full name is SYS SYS, provides a great many
independent services; it is really a timesharing system for
many trusting processes, each of which is controlled by a
single bit in the system variable SUPCOR. Setting the bit for
a process causes the process to run, and clear the bit. The
process should never run for very long, or it may tie up the
system by making the services of the other processes
unobtainable. If a process wishes to run continually, it does
so by setting its bit in SUPCOP. SUPCOP is or'ed into SUPCOR
every second, so a process whose bit in SUPCOP is set will be
run again that often. The process is always started the same
way, but it can of course have state variables.
The reasons why a given activity may involve the system job are
1) it may wish to print a message on the system log terminal, or
2) it may need to run in a job (eg, do system calls), but not be
associated with any one job, or
3) it may need to be able to hang up for short periods of time,
but the need to do it may be noticed at a time when that is
impossible, or
4) it needs to be done once every two minutes or every two hours.
The routines for those "very slow" and "super slow" clocks are in
the system job.
Re-initialising the connection to the IMP is an example of reasons 1
and 2. Typing "console free" messages is an example of reason 3 - it
involves doing I/O to the terminal, but it isn't done until the last
stage of killing a tree, when waiting of any sort would allow PCLSR'ing,
which would leave things in a screwed-up state. An example of reason 4
is the detection of core-link files which have not been used for more
than 2 minutes.
A complete list of the system job's functions follows:
a: Allocating or Deallocating Memory for Job Slots.
Most of the memory occupied by the system is marked as belonging to
the system job. For that reason, the way more is allocated for user
variable blocks is by having the system job do a .CORE UUO. This is
somewhat of a historical crock. Creating a job does not require such
allocation if there are free slots in the memory already allocated.
However, it may need to. For that reason, if the system job is hung
up, often jobs cannot be created.
b: Printing Various Messages on All Terminals.
Sometimes, messages such as "ITS GOING DOWN IN ..." or "ITS BEING
DEBUGGED" are printed on all the terminals in the world. It is the
system job that prints them on terminals which are free. Consoles have
them printed by DDT, however.
c: Checksumming the Constant Areas of the System.
The system job is always checksumming parts of the system and comparing
the checksums with those previously calculated. This mechanism causes
the clobberage of a word in the code of the system to be detected. If
only a single word in an area is clobbered, which word it is and the
original contents can be detarmined. In any case, a message is printed
on the system log terminal when clobberage is found.
d: Determining the Date and Time.
e: Detaching Trees.
When a top-level job is halted by a fatal interrupt, it is the system
job which executes the DETACH system call to detach it. Similarly, it
is the system job which detaches trees controlled by TV terminals when
the TV system crashes, and trees controlled by dialup lines whose
connections are broken (only when the hardware can detect that).
f: Depositing in the System.
When a job deposits in the system using .SETLOC or .IFSET, the system
job is informed so that it can update its checksums and avoid a system
clobbered" message. It also makes the change.
This used to be a great screw, in that if the system job were hung, it
could not be fixed by depositing in the system. Now, .SETLOC will do
the work itself without calling the system job, if the system job
appears to be hung.
g: Printing "Console-free" Messages.
When a terminal ceases to be in use, the system job is signalled to look
at all terminals and print console-free messages on all those which have
recently stopped being in use.
h: Logging Out.
The final stages of killing a job must be run by some other job. When a
top-level job is being killed, it does some of the work itself (kills
its inferiors and closes its channels). That is to make sure the
system job never hangs up trying to do it. The rest of the work is
then done by the system job, which can afford to wait for short peiods
of time when the job is almost killed.
i: Reinitialising the NCP.
When the connection to the ARPA network goes down, the system job gives
interrupts to all the jobs using the network, and also checks every so
often whether the network is useable again.
j: Printing of Various Messages on the System Log Terminal.
Events which cause messages on the log terminal include logging in,
logging out, writing on a directory whose name starts with "SYS",
garbage-collecting a disk directory, creating a disk directory,
gunning, parity errors, NXM errors.
l: Spooling the LPT.
On the AI KA-10 and the ML KA-10, the system job checks periodically for
spooled files and prints them.
m: Starting Other Demons.
On DM, the system job checks for any domon programs which have been
signaled. If there are any, it loads them into newly created jobs
and starts them.
n: Reinitialising the TV System, or Noticeing that it is Down.
2. THE CORE JOB.
This job, whose full name is CORE JOB, allocates core to jobs that
request it, and also frees up memory for use as user variable blocks,
which have to be allocated consecutively, by relocating the old
contents. Before there was pageing, the core job used to do shuffling.
3. DEMON JOBS.
a: The Comsat.
This demon, always named after some spacecraft or rocket, is responsible
for handling mail. Requests to send mail are placed in the .MAIL.
directory, and are eventually processed by the demon. The demon is
necessary because it may not be possible to send mail to other machines
right away, and in any case the user should not have to wait the time
it takes. It also provides other services such as forwarding.
b: NAMDRG.
This demon maintains the list of logged in users which appears on all
free TV consoles. It also updates a file saying when every user
logged out last. It exists on the AI KA-10 only.
c: PFTHMG DRAGON.
This demon updates the logout times file and keeps track of each user's
total CPU time. This demon originated on the ML KA-10, but has run on all
ITS machines at one time or another.