next up previous
Next: Higher-level Naming Up: Linkage in the Nemesis Previous: A Concrete Example

Pervasive Interfaces

It becomes very clear that certain interfaces within an application are used in almost all parts of the program. These include to some extent language support functions (such as those found in the C, C++ or Modula-3 runtime libraries). More important, however, are those interfaces which are inherently pervasive: these include the current thread, the user-level scheduler, and the minimal kernel. These are still notionally passed as call arguments, though in practice their use makes them seem more like part of the application's top-level context. It seems sensible to produce a convention (or a number of different conventions) whereby a well-defined set of interface references are passed implicitly with every procedure call. The implementation of this can then by optimised, for example by keeping the address of a record of these interfaces in a processor register. It is important to note the differences between this optimisation and the data segment pointer approach to text sharing described in section gif.

Firstly, only a small set of interface references are being kept. The use of these interfaces is so ubiquitous that they would be passed as arguments to every call in any case, or else copies of them would be maintained in many interface state records. In contrast, the data segment register approach keeps pretty much all the program state in one place, in a format which is highly application specific.

Secondly, what are being kept are still interfaces: their types are defined in Middl and the complete set of them available is ``written on the wall'' in the system for all to see. They represent an abstraction boundary, rather than being raw data.

Thirdly, they are there for convenience only. The basic philosophy remains the same and modules may choose to ignore the presence of pervasives. In particular, the low levels of the operating system do not use them at all and pass all interfaces explicitly.

One useful side effect of this is that standard components of a program can be replaced at runtime. It is even possible to instantiate a set of modules implementing a program in an entirely ``caged'' environment, where even the operating system is being emulated, while other instantiations of the same program sharing the same text run ``native''. This has obvious uses for debugging purposes, and is a considerably cleaner approach than linking with debugging libraries.


next up previous
Next: Higher-level Naming Up: Linkage in the Nemesis Previous: A Concrete Example

T. Roscoe