It should be mentioned that this specification is not at all concerned with the contents of the outer two rings; these rings constitute our principal products. The concern for a system design is to allow the greatest possible latitude to those designing and implementing these products.
This specification is also not concerned with the exact contents of the system service ring. This specification is concerned, however, with the forms of program interaction provided by these services. Essentially, this document specifies the concepts which are available and the limits of what can be done with them.
Since keys are “protected” they may only be kept in privileged pages called key pages. A key page may appear in a user’s address space (and must in order to directly address it), but the user never has write access to it. Keys are required in order to do almost anything in the system so most programs will have at least one key page in their address space. System calls are used to move keys from page to page, so that the user may control the distribution of his keys.
One key page called the “space page” is naturally associated with every process and is used to describe the layout of its virtual memory. The first 256 words of the space page have a one to one correspondence with the available 256 slots for pages in the Sigma 7-virtual memory. The programmer arranges his memory by placing page keys in the appropriate slots in the space page. This in general requires that the space page itself be in the virtual memory of the program.
This facility is roughly the same as the relabeling facility available on the 940 with the exceptions that words instead of six bit bytes are used as page identifiers and that any page in the system to which a user has access may be referenced this way.
Note, in particular, that the structure of a file has not been specified. For this reason, a user is free to set up his file structure in any convenient way. In this context, key pages play the role of index blocks on the 940. Similarly, key pages also play the role of file directories, so that the user can maintain his own directory structure.
It is fairly clear, however, that much is to be gained from establishing certain standard ways of doing common I/O and file structure tasks. Standard file structures are needed to achieve reasonable economy in the programming of language processors and other programs which routinely do file manipulation. Certainly some machinery is needed to insulate the average user from all the flexibility and to insure normal interchangeability.
The situation can be somewhat more improved by making the package a collection of shared pages, but this requires that all users of the program agree on the virtual address of the program during execution. This works acceptably well on the 940, but the shared program cannot be protected from read access or copying. There is also no way to give such a shared program special privileges unless ordinary users are denied any access to them. (It should be noted that any program can be automatically relocatable and shared by dedicating two index registers to be used as base registers and making all internal references indexed. This technique will probably not find wide use, however.)
A more elaborate solution to the packaging problem is provided by gates. As described above, a gate is the entry point to a program completely external to the caller. Access to the gate is, as usual, represented by a gate key. Invocation of the gate program is caused by the monitor detecting a branching reference to a gate key. (How this will be encoded in the Sigma 7 instruction set has not been decided yet.) The monitor then proceeds to establish the gate program as a working process. The user may pass the gate program various parameters, including keys. In particular, a key to the program’s space page may be passed, which allows the gate program to perform any desired manipulation of the caller’s virtual memory. For example, the gate may perform multiple buffering for look ahead purposes, I/O list-directed input or output operations, or any other service function.
A further facility allows a user to specify the interpretation of the CAL instructions. A sixty-four word region of the space page is dedicated to receiving keys; one type of key causes control to be passed to a user routine in the current address space; a gate key causes the gate program to be executed when the CAL is called.
Gates provide a mechanism for creation of processes also. In general, a gate may be used in three ways: a program may jump through a gate creating a return gate to the calling program, it may jump through the gate with no provision for returning, or it may fork off a new process which begins execution of the gate program while the caller continues. As a further generalization, every process, when temporarily suspended, looks like a gate to the system.
Gates provide a very attractive solution to many problems:
Many of these functions are straightforward, but some of them, such as blocking for input and output and escape, bear more discussion. The essential element in handling these functions is the Event Demon, whose duty is to assist the scheduler in deciding when to run processes whose activation depends upon asynchronous events such as the arrival of a break character.
When a process wishes to block upon the completion of some event, it merely calls the Event Demon with a key to the indicated event. When another process (e.g., the Terminal Demon) wishes to notify the blocked process that its event has occurred, it calls the Event Demon with a key to the “happened” event. The Event Demon, which has a gate key to each of the blocked processes, merely forks off the blocked process and returns to the caller.
The workings of the Terminal Demon now becomes fairly simple. If a program requests input or has generated a great deal of output and must be blocked for a while, the Terminal Demon requests an event key to be created and calls the Event Demon to be blocked. When conditions are right, the Terminal Demon again calls the Event demon to “cause” the unblocking event. The process is restored to execution and continues on its way.
Escape is handled in a somewhat unique manner. To handle escape in the manner of the 940 requires a considerable amount of machinery within the system itself for controlling processes. The approach taken here is somewhat simpler for the system and provides more flexibility.
A simple mechanism added to the Terminal Demon will allow a very general escape facility. Specifically, two processes can be made to time-multiplex the same input channel. Each process may request the channel be assigned to it and may block for lack of input. Externally, the user may also control the destination of the input characters. In particular, escape is a character whose function it is to chance the switch on the input channel to activate the other process. The other process, if it has been given sufficient privileges, can stop the first process, examine it as it is running or whatever.
To some degree handling escape is a little more involved than it is on the 940; however, standard gates will exist as library routines for default situations.
As described above, each running process is assigned an account which supplies the “fuel” to keep the process running. At the user’s discretion, he may create subaccounts to limit the amount of computation a process may do. The account may also be used as a switch to stop any processes which are dependent on it. A system call known as “global search” may be made to return a gate key to each process which is running under a given account. Given sufficient authorization in the form of keys, the controlling process can examine the state of the stopped process and eventually restart them by forking.
In the area of design, a great many questions cannot be answered without some actual experimentation and development of data on usage patterns. Consider, for example, the problem of deciding on the use of disc versus RAD for the placement of file data. What kinds of algorithms are best for deciding where a page should be? Perhaps the throughput gained by promoting files to RAD for working storage exceeds the cost of both the extra RAD space desired and the time spent in promoting unused data; perhaps not. We don’t know enough about how systems are used today, let alone how they will be used in a year or two.
For system designers these are pressing problems. The only acceptable answer is to provide a structure where the system answers change when conditions require it. If the costs of system change are high, the first answer is likely to be the last one. During development stages, questions of performance are not particularly important. Software projects are not held up because the system can only support ten users rather than forty. The important requirement is that the system be functionally complete, so that many people are not waiting for the debugging of a single critical feature. Or worse, using a partially debugged feature only to find its specifications changed to eliminate an exceptional problem. Again, the ability of a system to withstand change allows designers to focus on functional performance first and efficiency later, the order which makes most sense.