- 3 -
The daemon checks the page table entry for the page to see if the `page used' bit is set. If not, the page can
be made available. If it has been modified, it must first be written out (asynchronously). If the page has
been referenced, the daemon resets the `used' bit and proceeds to the next core map entry. If the page has
not been touched the next time round, it will be freed. On systems with large memories, a complete cycle
can take some time, and so recent versions have the daemon cycling two pointers through the map: one
clears `used' bits; the other reclaims pages.
In principle, this is a simple and elegant technique. It has been applied quite effectively in a controlled
environment in a new implementation of file cacheing in UNIX using virtual memory [Bra89]. There are,
however, several problems in practice with the algorithm when applied to UNIX processes, at least in its
SunOS 3.5/BSD 4.2 version: the core map must keep a back reference to a page table entry, a process's
working set size is not always accurate, and the memory scheduling algorithms are elaborations of the early
`swapping' algorithms.
The daemon must be able to locate `the page table entry' for each page. The core map entry for a physical
page must therefore point back to the page table entry that refers to it, if there is one. Map entries for data
and stack pages store a (process, page) pair. Pages of an executable program, though, can be referenced by
several such entries, which must all be found. The solution adopted is to store (text-table, page) in the core
map. Processes using a given executable are linked in a chain from its text table entry. Whenever one of
the processes' page table entries changes, owing to page in or page out, all others must change to match it.
The pageout daemon looks round the list too, in order to calculate the union of used/modify bits for all
processes referring to the page.
When the page daemon takes a page, it invalidates the page table entry but leaves a reference to the page
(the page frame number), so that should the process soon fault on that page it can reclaim the page directly
from the free list. Before any process is given a free page, the memory allocator must therefore clear any
reference to it, using the data in the core map in much the same way as the pageout daemon. Just to liven
things up, in 4.2BSD the network system can claim pages at interrupt level using the memory allocator, so
that a process's page table entries can be changed by an interrupt! (In practice this is not a problem pro-
vided care is taken at the kernel main level, but it is something else to have to reason about when checking
the code.)
To reduce overhead, the old pageout daemon does not run until the amount of free memory drops below a
specified value. It then cycles round the core map at a rate that depends on the amount of memory left. If it
cannot free enough memory quickly enough, the memory scheduler (swapper) is started. The swapper syn-
chronously writes to disc clumps of the modified pages from the whole image of each process it selects.