Domains are the actors of the system. Any change in the system is the direct result of some domain action.
Domains can send messages to other domains by invoking gate keys, or to the kernel by invoking primary keys. These messages can be sent upon explicit instruction of the program, or implicitly upon exceptional circumstances called traps or faults. These exceptional circumstances include invalid instructions in the program or reference to invalid portions of a segment.
The most common action of a domain is to execute the instructions found in the domain's segment. In the absence of traps, faults, or key invocations, these actions only change the domain and the domain's addressing segment.
Three types of keys, domain, start, and resume, cause the kernel to view the node they designate as a domain root.
A well-formed domain root contains node keys that designate two other nodes. Together, these three nodes form the domain. Nothing in the nodes specifically identifies them as part of a domain; when describing them as a domain, they are presumed to be well-formed.
The names C0 through C15 refer to the 16 slots of the root node of a domain. The names C16 through C31 refer to the slots of the node designated by the node key in C14. C16 through C31 are frequently referred to as slots 0 through 15 of the domain (since they act as the key registers of the domain).
C0 holds the domain's brand. It is used with the domain tool key for rights amplification and is inaccessible through a domain key. It does not influence the execution of the domain.
C1 holds a meter key that indicates authority to expend resources. The domain is said to depend on the meter.
C2 holds a key to the domain keeper.
C3 defines the root of the addressing segment. It holds a memory key.
C4 is a data key whose right 6 bytes hold the domain PSW. Parts of the domain PSW correspond to parts of the S/370 PSW described in the IBM System/370 Principles of Operation. Some parts of the S/370 PSW are inaccessible to domains. The format of the domain PSW is (each character designates a bit):
If P is 1, C7 through C9 will control the PER hardware.
CC is the condition code and MMMM is the program mask.
LL is 11 if SVC 253, 254, and 255 are to be interpreted as key invocations, and 00 otherwise.
AAAA AAAA AAAA AAAA AAAA AAAA is the instruction address.
C5 holds a data key which defines the trap code. It must be DK(0) for the domain to run.
C6 holds a data key which controls the monitor call trap. See the section in this chapter entitled "Program Surveillance".
C7 through C9 hold data keys which control the Program Event Recording hardware. PER traps will not occur unless the P bit of C4 is one. See the section in this chapter entitled "Program Surveillance".
C10 and C11 do not influence the process in the domain. They may be used for the convenience of the domain key holder.
C12 holds a data key which contains the priority of the domain. It is maintained by the kernel when the process-running bit of the domain root is TRUE. C12 is inaccessible through a domain key.
C13 is the busy flag. It holds DK(0) while the domain is available and holds DK(1) while it is busy. It is maintained by the kernel when the process-running bit of the domain root is TRUE. C13 is inaccessible through a domain key.
C13 will receive a DK(0) when the domain becomes available and may receive DK(0) at times after it becomes available until it is entered again with a start key or the node is severed. The kernel will not place anything except DK(0) or DK(1) in C13. If something else is placed in this slot the domain may not run. C13 will receive DK(1) any time the domain's process-running bit is one.
C14 holds a node key to the keys node. It is used with the domain tool key and is inaccessible through a domain key.
C15 holds a node key to the registers node. It is used with the domain tool key and is inaccessible through a domain key.
Programming note: C10 is frequently used to hold a segment key to the symbol table for the domain's keeper.
C16 through C31 are the key registers. These slots can supply keys to be invoked by the domain or passed as key parameters, or can be used to receive key parameters.
If the domain is allowed to invoke keys (determined by the "LL" bits in C4), the key registers are controlled directly by the program in the domain. If the domain is not allowed to invoke keys, the key registers are inaccessible to the program.
The registers node contains 16 data keys that define the contents of the general and floating registers of the domain. Each of these keys contributes its low 6 bytes as shown in Figure 2-2.
As the process in the domain changes the general and floating registers, these data key values change. This operation may be optimized (the values cached) so the domain executes instructions that change registers at the full execution speed of the underlying hardware.
Bytes in these data key values, other than the right 6 bytes, do not affect the registers and vice versa.
A node that is a domain root is said to be well-formed. A node that the kernel attempts to interpret as a domain root and is not a domain root is said to be malformed. In general, a node is well-formed if it conforms to the specifications of the object which it is supposed to represent by virtue of the type of key which leads to it. That is, a node may act as a root node of a domain, a segment node, or a meter, depending upon the key referencing it. If the node does not meet the specifications, it is malformed with respect to functioning as that particular type of object. Thus a node may be well-formed as a meter, but at the same time malformed as a domain root node.
A process in a malformed domain will not issue instructions or take other actions; it may vanish (with no trace) or cause a trap. The following circumstances cause a domain root node to be considered malformed:
Programming note: Some versions of KeyKOS may redefine as well-formed some domains that are defined here as malformed. Programs should not depend on the effects generated by malformed domains.
Programming note: This document describes domains as if they are not primitive. This means that programs outside the kernel build domains from nodes. The system was designed to allow only one program, the domain creator, to hold the domain tool key and thus be the only program that depends on the particular way domains are built from nodes.
Some implementations may have domains as a primitive object. In these implementations, there would be no domain tool. The domain creator, which will return a domain key to a new domain, would instead be a part of the kernel. Programs should not depend on this difference.
A domain is in exactly one of three states: available, running, or waiting:
Every action in KeyKOS takes place as a result of some action by a running domain. The kernel allows (one or more at a time) domains in the running state to execute. The order, and for how long, is up to the kernel.
A domain in the running state will take the following actions.
If either the domain's C1 contains a valid meter key, or its trap code begins with X'0500000001' (the code for meter traps) then:
Otherwise (the meter key is not valid and the trap code is not TC0 = 5, class = 1), then a trap code is stored with TC0 = 5, class = 1, and a subcode as defined in the section on traps. (Since the domain's process-running bit remains on, the trap action will then occur as described above).
Invocation is the fundamental way to request services designated by a key. The domain program that issues an invocation must hold and designate a key. If the key is a gate key then the invocation is called a gate invocation.
During a gate invocation, the process running-bit may become false in one domain and will become true in a second domain. The second domain will start running immediately after the first has stopped.
The parameter mechanism in invocations is a call-by-value mechanism. i.e. All parameters are copied.
Programming note: The parameter word may be interpreted as an order code or return code, depending on the circumstances.
CALL (SVC 253) - The invoking domain enters the waiting state (i.e., its process-running bit becomes FALSE). The last key parameter passed is always a newly created (by the kernel) return key to the invoking domain. In anticipation of that return key being invoked (by some other program), the domain normally loads an entry block before executing a CALL.
RETURN (SVC 254) - The invoking domain's process-running bit becomes FALSE and the domain enters the available state. In anticipation of some start key to this domain being invoked (by some other program), the domain normally loads an entry block before executing a RETURN.
FORK (SVC 255) - The invoking domain remains running. Since it remains running, no entry block is loaded.
In an implicit invocation, the CALL invocation is simulated by the kernel, loading an entry block which specifies no keys, a zero parameter word, and a zero length parameter string. The invoking domain enters the waiting state and a resume key is created by the kernel and passed as the fourth key parameter.
The invoked key must be a gate key or the Error Key. If it is not, the implicit invocation does not take place and the invoking domain is left in the waiting state.
Design Note: X'80000000' (the alleged type call convention) is never generated as the parameter word for an implicit invocation. This allows domain, segment, and meter keepers to implement this convention.
The invoking domain provides an exit block in general register 0. Bits 6, 7 and 12 through 15 of this block are reserved and must be 0. The format of the exit block is:
The invoking domain specifies the parameter word by loading it in general register 1.
If AA is 00, a zero length byte string data parameter is provided.
If AA is 01, general registers 2 and 3 specify the address and length respectively of the byte string data parameter. The length, in register 3, is considered as a 32-bit unsigned integer. The length must be less than or equal to 4096. If it is not, the trap code is set with TC0 = 5 and subcode 6.
If AA is 10, the trap code is set with TC0 = 5 and subcode 2.
If AA is 11, general registers 2 and 3 specify the address and length of the argument string within the registers. For this purpose the 32 bytes of floating registers 0 through 6 are considered to follow and be contiguously adjacent to the 64 bytes of the general registers.
For i from 1 through 4:
If a CALL is specified then a return key, produced by the kernel, becomes the fourth key, and bit 3 and bits 28 through 31 of the exit block are ignored. However, the invocation may be faster if these bits are 0.
All key invocations proceed in two steps:
If the key being invoked is a resume key, all copies of it become DK(0).
The state of the invoking domain is adjusted according to the type of invocation (CALL, RETURN, or FORK) and its instruction address is advanced to the next sequential instruction.
In some implementations, a FORK invocation of a gate key may stall when establishing the new domain as "process-running" would exceed a process-running limit built into the kernel. In this case, the kernel may call the decongester to help. The domain issuing the FORK need not be aware of this.
If a start key is specified and the designated domain is busy, the invoking domain stalls. If the invoking domain is still at this point when the busy domain becomes available, the invocation will then proceed.
Some implementations may not recognize that the situation leading to the stall has changed in some way other than the invoked domain becoming available. In these implementations, the invoking domain will not proceed until the invoked domain becomes available or some other implementation-defined event occurs. Thus, if the invocation instruction that had caused the explicit invocation were changed to a NOP, the invoking domain would remain stalled despite its process-running bit being TRUE and the lack of an obstacle.
Normally, stalled invoking domains are restarted in the order that they became stalled. This is not always possible.
All the action of invoking a key depends on (uses the resources of) the meter of the invoking domain.
Design note: It might seem reasonable for a version of KeyKOS to provide buffering to avoid stalling. In this case, the invoked key and parameters would be held in a message and the disposition of the invoking domain would occur immediately. For example, a domain executing a FORK of a start key to a busy domain could find that the FORK completes (i.e., the domain goes on to the instruction after the FORK) while the action of invoking the start key has not yet occurred. This has not been implemented because of the difficulty of accounting for and limiting the storage required for the messages.
There are three kinds of resume keys:
If the invoked key is a start or return key, the entry block for the invocation is taken from floating register 2 of the invoked domain.
If the invoked key is a restart or fault key, the entry block will be X'10000000' (no parameters are accepted).
The format of the entry block is:
If C = 1 then the parameter word will be placed in general register 1 of the invoked domain. Otherwise, register 1 is unchanged.
If S = 1 then general register 4 holds the address (in either the invoked domain's virtual memory or its registers) of the parameter string, and register 5 holds the maximum length of the parameter string.
If L = 1 then the length of the argument string will be placed in general register 3.
If the argument string is shorter than the maximum length specified for the parameter string, values beyond the length of the argument string will remain unchanged. If it is longer, the remainder of the argument is not transmitted.
If R = 0 then the parameter string is in the invoked domain's virtual memory.
If R = 1 then the parameter string is in the invoked domain's registers. For this purpose the 32 bytes of floating registers 0 through 6 are considered to follow and be contiguously adjacent to the 64 bytes of the general registers (see Figure 2-5).
If some of the parameter string is in a page that is not defined read/write in the invoked domain's addressing segment, and some part of the argument string is to be placed in that page, then an addressing trap code will be produced in the invoked domain even when a write reference to that address by a problem mode instruction in the invoked domain would have caused a call invocation to a segment keeper. No segment keeper will be called. It is as if the reference to the parameter string had been made via a memory key with a no-call bit. In this case the portion of the argument that was to have been copied into that page is not copied but the rest of the invocation action proceeds.
If S = 0 then the argument string is not accepted and R and L are ignored.
If D = 1 then general register 2 of the invoked domain is set to a value determined by the gate key. If the gate key is a start key, the value is the data byte of the start key with 24 high order zeros. If the gate key is a resume key, the value is zero.
For i from 1 through 4:
If a return key to a running domain is invoked, the arguments may be deposited in the invoked domain (according to the invoked domain's current entry block in floating register 2) and the process-running bit will remain TRUE. If any resume key is used to a running domain, that domain may lose its place on some queue.
Programming note: Domains will never overlap with the current design of space banks and domain creators, if current domain creators are the only holders of the domain tool.
Each of these domains can be described as different objects of the same type.
Design Note: The trapping caused by rejected parameter words is inhibited for restart keys to prevent holders of restart keys from influencing (beyond impeding) the domain designated by the restart key.