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. Usually 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 produces 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.

In all of these cases the recipient of the message is identified by a key; for a message from a domain, the program obeyed by the domain selects the key; messages to keepers are addressed via a start key found in some keeper slot. When a kernel object delivers a response message it demands that the recipient be addressed by 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 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.


The program also interprets received messages whose data formats are self defined in part.
If the invoked key is a gate key then that key designates a domain and the program that that domain obeys has already specified what slots and memory the message is to be delivered in. That program will also examine the message and determine its meaning.
The program designates the slots into which to receive keys from incoming messages.

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. 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. In C code the pattern was usually to define a type which was a struct with fields depicting the marshalled 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 programer 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.