Messages are produced and consumed by domains as they obey user code that directs the detailed building and interpretation of those messages. The kernel passes these messages between domains but the kernel produces and consumes messages as well. When a key to a kernel object is invoked, the kernel interprets the message and usually prepares a response message. In the keeper pattern the kernel generates a message for a keeper. Such messages may best be viewed as being produced by the domain whose action caused the event that the kernel’s message reports. In this case the logic of the program that the domain is obeying is not ostensibly responsible for the message. In such cases we sometimes say that the domain implicitly invoked the key in the keeper slot, in contrast to when the domain code explicitly constructs the message.

(2017) There is the following ambiguity in much Keykos documentation in the phrase “domain invokes a key”. The two situations are:

In the remainder of this note I will say message from the “domain’s program” for messages constructed by the program that the domain obeys, and messages form the kernel for messages constructed by the kernel concerning some domain.

In all of these cases the recipient of the message is identified by a key; for a message from a domain’s program, the program obeyed by the domain selects the key; messages from the kernel, to keepers are addressed via a start key found in some keeper slot.

When a kernel object is invoked by a fork or return, there is no automatic generation of a resume key and any response from the kernel object is silently discarded unless the fourth key in the invocation message is a resume key.

Memory keys and meter keys serve their purpose without messages although some attempt has been made to make it appear as if a reference to memory by a domain were as if there were a message delivered via the nodes to the page. This illusion is incomplete.

Building messages — Practice and Prospect

In Keykos things are tied together by capabilities, which are called keys. Messages between objects are always in the chain of causal events; indeed by some perspectives they are the entire chain of causal events.

Domains obey externally supplied programs and hold keys. The recipient of a message is determined by a key that the sending domain must already hold and that the program designates as it invokes that key. (In Keykos the domain holds 16 keys and the program designates a key by a 4 bit index within the program.) The message is composed of data and four keys. To send a message the program dynamically composes the message by computing the data and selecting the keys from those that the domain already holds.

If the invoked key is a gate key then that key designates a domain and the program that that domain obeys has already specified into which slots and memory the message is to be delivered. That program will then examine the message and determine its meaning.

Marshaling Messages

In the 370 version the practice was for the application to write code to explicitly construct the message by marshaling the data of the message into contiguous memory before the send. A fair amount of code was written in PL/I which has variable length strings as a first class type and we thus expressed marshaling as a PL/I expression involving concatenation. PL/I strings held arbitrary binary data including zero bytes. This was moderately fast and moderately convenient but it was considerably slower than languages where the programmer was forced to use more elementary language features — it was also somewhat easier to read. The usual pattern for C was to define a type which was a struct with fields depicting the marshaled message. Ordinary C code would fill in these fields. gcc’s Compound Literals provide convenient and fairly fast data marshaling.

I think that ASN.1 was conceived as a scheme for defining wire formats for messages. I don’t see how the requirements differ from those of sending capability address messages except that such messages must also include capabilities. ASN.1 tools are available to produce marshaling code but I wonder about how thick the manuals are that the programmer who codes the call site are. Also how thick are the manuals for those who define new messages for new objects.

An even more obvious candidate is some interface definition language with attendant tools. Keep in mind in either of these: the manuals must be understood in order to understand the systems implemented with these tools.

Some marshaling tools may enable Trojan horses. If I write a Macro or routine or language style object for you to use when you code invocations of my object, I may be in a good position to cause such invocations to pass more authority to me than you expect. Tools must be selected with this danger in mind. If I must know how to read, and read the IDL for each thing I use, perhaps my job is not eased by such tools.