The provision of paging of file content leads to the possibility of demand paging for programs, enabling them to be loaded into memory dynamically and to have only the active portions of those programs resident. To achieve this, programs must be appropriately initialised in new tasks, with a page fault handler configured to provide program file content whenever a region of the program payload is encountered that is not currently resident in memory.
To load and initialise a program, a new task must be created, defining a separate address space for the program and allowing it to operate independently of other programs. For a program to actually run, a thread of execution must be created so that the program's instructions can be read and processed. Once running, the program must be able to interact with the system environment and to have its memory resources made available to it upon demand.
A number of elements must be prepared to be able to run a program, these being summarised below.
The program executable file is obtained and the program metadata loaded, identifying the memory regions and entry point (the location of the first instruction).
A new task is created to hold the program. For this new task, new threads are created to run and support the program. One thread will run the actual program, and another will be used as the region mapper to handle page fault conditions.
Memory is allocated for the new program's threads, particularly the stack for each thread.
Each stack is populated with program argument and environment information. Of particular importance are the capabilities to be made available to the threads since these permit interaction with the rest of the system.
The capabilities to be used by the threads must be mapped into the new task.
To connect the main thread of the program to its region mapper, an IPC gate must be created. This is mapped to the new task where the region mapper will bind to it, using it to expose its interface.
Thread properties such as pagers and exception handlers are defined for the threads, with the main thread employing the newly created IPC gate capability to delegate paging to the region mapper.
When satisfying page faults for a task, one approach involves situating the page fault handler within the task itself, this managing the available memory regions and employing receive windows when requesting memory pages.
The general arrangement involving such internal page fault handlers for a program in a task is as follows:
Another approach is to employ an external page fault handler in the creating task. When a page fault occurs, the external handler ensures that the appropriate content has been brought into its own memory space. It then returns a flexpage from the handler routine to resolve the fault.
This arrangement may be used to support a program deployed in a task. Since an internal page fault handler is just another kind of program, this external pager arrangement can be constrained to only supporting an internal page fault handler deployed in a task.
To provide an internal page fault handler alongside an actual program to be run, the following arrangement is used:
The creating task performs the following operations:
Upon starting, the program will encounter a page fault immediately, unless some additional work was done to map memory pages into the task in advance. The internal pager or page fault handler will attempt to resolve these faults as they occur, being contacted by the kernel on the program's behalf.