Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 18: Page Reclaim and Swapping


else if (is_locked)
referenced += page_referenced_file(page);
else if (TestSetPageLocked(page))
referenced++;
else {
if (page->mapping)
referenced += page_referenced_file(page);
unlock_page(page);
}
}
return referenced;
}

The function sums up the number of references the page has received lately. IfPG_referencedbit is set,
this is clearly a reference and counted accordingly. Note as per the previous discussion the bit is removed
if it was set.


If the page is mapped into some process address space, the references to the page must be determined
via the hardware-specific bits in the page table. Recall from Section 4.8 thatpage_referenced_anon
computes the number of accesses to a page in an anonymous mapping, whilepage_referenced_file
does the same for file-based mappings. On IA-32 and AMD64, for instance, this amounts to summing the
number of page table entries that point to the page in question and have the_PAGE_BIT_ACCESSEDbit set,
which is automatically updated by the hardware.


page_referenced_filerequires that the page is locked (to protect, e.g., against truncations that would
erase the mapping while the kernel is operating on it). If an unlocked page is passed topage_referenced,
the page is locked. Notice that thelastelse branch will be executed for an initially unlocked page because
TestSetPageLockedwill return the value of thePG_lockedbit before changing it to one. Should the page
have been locked from some other part of the kernel in the meantime, then it does not make sense to
wait until the lock is released. Instead, the reference counter is just incremented by 1 because at least the
process that initiated locking the page has accessed the page.


Note thatpage_referencedwill (viapage_referenced_one,employedbybothpage_referenced_file
andpage_referenced_anon) also mark a page as referenced if the system currently undergoes swap-
ping and the page belongs to a particular process that holds the swap token — even if it has not been
accessed from somewhere. This prevents pages from this process from being reclaimed, and will increase
performance in situations with heavy swapping. See the details of this mechanism in Section 18.7.


Finally, there’smark_page_accessedto consider. The implementation is straightforward:


mm/swap.c
void fastcall mark_page_accessed(struct page *page)
{
if (!PageActive(page) && PageReferenced(page) && PageLRU(page)) {
activate_page(page);
ClearPageReferenced(page);
} else if (!PageReferenced(page)) {
SetPageReferenced(page);
}
}

This implements the state transitions illustrated in Figure 18-13. They are additionally summarized in
Table 18-1.

Free download pdf