Here are some collected notes on keepers, but see, perhaps, a slight rant on the subject first.

The idea of a keeper is loosely that of a routine that gets control when something unusual happens. There are many instances of this idea in operating systems.

One of the advances in Keykos was to remove from the shared kernel, most of the definition of the response to such events. Two benefits resulted: Conventional systems may provide useful user selectable responses to these events from a fixed catalog but these scarcely exhaust the possible uses to which such signals can be profitably put, and the semantics of these responses burdens security arguments. Most conventional systems will give control to a program in the address space of the program that caused the fault with enough information to repair the fault.

In most operating systems a user program can request notification of the exceptions that it causes but there is no way for one program to request notification of access to invalid portions of some particular memory object, or to be notified when another program exceeds some resources. These limitations preclude a number of tactics. The original hardware exception was often designed to present a virtual construct to the program, such as virtual memory or virtual continuous operation (hiding the effects of time slicing). The program is unaware of the operating system acting on exceptions in support of these virtual constructs. The operating system hides evidence of the exception. In Keykos the program that reacts to these exceptions is called a keeper and is typically hidden from the program that caused the exception just as the kernel is hidden from the user program. The keeper thus resides outside the kernel but also outside the typical application. Capabilities provides a natural answer to “What authority should the keeper have?”. As a consequence the keeper I invent for my application is not in your TCB.

In Keykos the virtual memory of a program is composed of segments. Each segment may have its own keeper. A keeper for a segment is installed by the creator of the segment. If I create a segment and grant you access to that segment, then it is my keeper that will react to memory faults within that segment caused by your program. I am in a position to create data within the segment upon your referencing some new portion of the segment providing the illusion that the data was already there. You may be concerned that my keeper not have access beyond that necessary to provide the missing data. In particular I should not have access to your authority or even be able to read your address space, except for my segment that appears there.

Remote Segments

Other custom keeper functions can be provided as well. Keepers have been designed that provide the illusion that a mutable segment is resident simultaneously on remote machines. This requires that respective keepers on the machines can communicate. A particular page of the segment is in one of these states: Memory faults detected by the hardware cause a message to the keeper who causes a state transition for a given page, perhaps preceded by transmission of the page content. This is the MESI protocol used by many microprocessors to coordinate the caches of multi processor systems.

Other notes bearing on keepers in Keykos:

The keepers in Keykos conform to the following pattern: We must inquire why some functions are in the kept object and others are in the keeper. Here are some discriminants: Here is a brief note on domain keepers.

Core Ideas of Keepers

I don’t know how many separate ideas or patterns there are. Here are some:

Keeper Warts

Composition

A dirty little secret about keepers is that they don’t compose. If two keepers exist for the same construct, it is not generally possible to compose them so as to have their combined benefits. Most often it is not possible to be clear what the combined specifications would be. Normally in combining advantages human judgment is necessary to allow for issues of precedence or ordering of effects. This effect manifests itself in Keykos in that the service keys are not meant to be shared. Nor is it feasible to design them so that they may be shared by programs that are unaware of each other.

Scheduling

Segment keepers and meter keepers have a problem with concurrent users of the kept object. A meter keeper is called when a meter runs dry. There may be several processes running under that same meter and it is possible that another of these processes will try to run before the keeper has replenished the meter. This is in fact likely if the keeper delays as a scheduling policy. Subsequent users of the meter will accumulate on the keeper’s stall queue. When the keeper replenishes the meter and restarts the originally trapped domain, the kernel will note that the keeper has become available and put just the first member of the stall queue on the CPU queue. Two of the scheduled domains will thus promptly resume operation but other queue members will await service from the worry queue server. This makes scheduling thru meters unduly sluggish. It has been suggested that a kernel tool be available to move all of a stall queue to the CPU queue. This would require a domain key or perhaps just a gate key to the domain with the queue.

If several users of a kept segment touch the same page before the segment keeper has had time to reify that page, the same problem arises. In practice the problem is much less likely for the keeper probably has no reason to stall. The keeper is likely to remove the obstacle by placing a key in a memory tree and become available by returning to the trapped domain. The keeper thus becomes promptly available to serve other faults. This means that one segment keeper domain can drive concurrent I/O operations. If the keeper removes the page by computing segment content contents, the problem with the meter keeper arises. The same proposed solution should serve in this case as well.


See this about some issues about extending the keeper pattern to objects defined outside the kernel.
The keeper pattern.