States of The Context StructurePreparing a domain to run involves constructing a Context structure for it. The trend in the EROS kernel is that more and more domain operations are being done on the Context structure. This makes sense, since the vast majority of those operations are machine specific and the Context structure is a natural place to put such things. The remaining domain operations are things like fabricating start keys or changing domain root slots; these are really operations on the domain root viewed as a node, and are accomplished by first unloading the necessary context state and then performing the operation on the node. In shifting more and more logic in the direction of the Context structure, however, we have introduced something of a catch-22. It becomes necessary to be able to fabricate a context structure for a malformed domain. This context structure need not be runnable, but it needs to be able to capture a fault code -- specifically the FC_MalformedDomain fault code. A particularly ugly case is that a malformed domain may not have a number key in the trap code slot. Since the context structure is a cache of domain state, it is not immediately clear in what sense we can set a malformed fault code when the domain root posesses no such slot. Fortunately, this particular fault code is an immediate consequence of the fact that the domain is malformed, and should be reset if the domain becomes well-formed. In this particular case, then, it is not necessary to be able to store the fault code value. As a side note, this approach drew to my attention a problem that already existed but I had failed to recognize. If a fault code is set due to a non-restartable instruction, and the domain root somehow becomes malformed before the non-restartable fault code is examined, the fault code generated by the instruction can be lost. My view on this is that in becoming malformed the domain's execution state became undefined. Unlike science fiction, you don't come out of undefined states intact. With all that as preamble, this note describes the states that a Context can have in the new design. Fabricating a ContextIn order to fabricate a Context, it is necessary and sufficient to have a node that is the domain root of some domain. The domain root note is if necessary unprepared, then marked as a domain root. The Context structure is made to point to the domain root and the domain root to the context structure. At this point the Context is said to be loaded. The domain root need not be well-formed. If the domain is not well-formed, the Context can be loaded, but it will not be possible to make the Context runnable. Preparing a ContextIn general, the goal in operations on a Context is to render the context runnable. All operations on contexts proceed by first preparing the Context to run. If preparing the Context to run succeeds, the Context will be marked runnable. The usual code sequence involved is:
Context *ctxt = domainRoot->GetDomainContext();
ctxt->Prepare();
if ( ctxt->IsRunnable() )
...
It may prove useful to have Prepare() return a boolean indicating complete success.The vast majority of operations in the kernel can proceed successfully only on a Context that is fully preparable (i.e. one that can be rendered runnable). The exceptions to this are those domain key operations that manipulate the structure of the domain itself (i.e. the ones that can alter whether a domain is well-formed) and those that get or set register values. In support of the latter operations, Context preparation can succeed partially. In simplified form, the sequence of states of a Context is: | State | Description |
|---|
| Loaded | The Context has an associated node that is a domain root. The domain root node may not constitute a well-formed domain. | | Well-Formed | The domain root node has been examined, all required domain annexes have been found, and all slots of the domain constituents have keys of appropriate type. | | Cached | The domain is well-formed, and all register values have been cached in the context structure. | | Runnable | All register values are cached, and the domain fault code is FC_OK, indicating an unfaulted domain. |
On some architectures, it is convenient to break out the annex validation and cacheing to allow subsets of a Context to be decached. In such implementations, the Context is considered cached only if all required annexes are cached. On some architectures, there can be annexes that are not required. These generally correspond to coprocessors that are not used by a particular process. On the x86, for example, the floating point unit is unused by most processes, and it's state appears in a separate annex node that need not be present for the domain to execute instructions. The first time such a domain executes a floating point instruction it will fault, and the Context logic then takes note of the need for a floating point register set. Well-Formed DomainsA domain is well-formed if all of the following conditions are satisfied:- It's annex slots hold node keys.
- It's fault code slot contains a number key.
- All annex nodes hold only number keys.
- All domain root register slots hold number keys.
- All constituents (annex node, domain root, key registers node if present) are distinct.
A domain that is not well-formed is malformed. A malformed domain's fault code is FC_MalformedDomain. Attempts to set such a domain running cause it's domain keeper (if one is named) to be invoked. Note that the following conditions do not render a domain malformed: - A key of inappropriate type in the segment slot. Such a domain is deemed to have a well-defined value in its address space register, which is a distinguished value indicating that all addresses are invalid.
- A key of inappropriate type in the schedule slot. Such a domain is deemed to be unable to execute instructions, but all of its register values are defined.
- A key of inappropriate type in the key register node slot. Such a domain is deemed not to posess keys, and cannot perform invocations.
Runnable DomainsA domain is runnable if all of the following conditions hold: - It is well formed,
- It is in the running state (and therefore is occupied by a thread)
- It has a zero fault code
A domain without a valid address space is runnable. Such a domain simply takes an access violation when attempting to access it's first instruction. A domain without a valid schedule key is deemed to posess a schedule conveying no CPU share. It is runnable, but will not make progress. Copyright 1998 by Jonathan Shapiro. All rights reserved. For terms of redistribution, see the GNU General Public License |