A domain differs from the normal concept of a user process in the way in which the processor is presented to it. In the case of a process, the processor is taken away from it by suspending it and is returned by resuming the process to exactly the state in which it was when it was suspended. This gives the illusion to the process that it is running on its own virtual processor; it also hides from the process any information about the current processor availability -- the process has no way of knowing when it has the processor.
In Nemesis, the processor is taken away from a domain by deactivating it; deactivation involves storing the state of the processor into a data structure shared by the kernel and domain, the Domain Information Block. When the domain is next scheduled, the processor is given to a domain by activating the domain; activation involves transferring execution to an address specified in the activation vector entry in the Domain Information Block.
For a domain supporting a traditional single-threaded model of execution, activation start up code would just restore the saved context and the user code would continue to execute. Another common use within the Pegasus project would be for the entry point to be a user-level thread scheduler. In this case the mechanism provides functionality similar to scheduler activations [.anderson sosp13 activations.]. Finally, some domains may be completely event driven, for example, device driver domains.
Hence it is simple to support the standard programming models on this activation model; in fact all operating systems do it, but it is usually the case that the asynchronous nature of interrupts and rescheduling events is hidden from the user level code.
The Nemesis mechanism provides a number of advantages for the types of multimedia applications we are considering. First, it provides a means of informing applications when they have the processor; a user-level scheduler can use this information, together with the current time, to make more informed decisions about the fate of the threads which it controls. Second, because thread scheduling is performed by the application, the user-level scheduler has direct control over the behaviour of its threads, and does not have to resort to describing their behaviour to a central scheduler in terms of priorities and deadlines. Third, once a domain is given the processor, it keeps it until its time quantum expires, or it voluntarily yields the processor because it has no more work to do. This avoids the problems encountered in kernel level thread implementations when threads block in the kernel and the kernel scheduler gives the processor which was running the blocked thread to a thread belonging to another process. Nemesis has no blocking system calls except ``suspend'' which will typically only be called by a domain user-level thread scheduler.