Fix the computation of used memory and add a TODO.

* The altered used pages calculation of hrev43168 wasn't correct, as
  the inactive page queue may (validly) contain mapped pages as well.
  Those would then get counted twice (as they are included in
  gMappedPagesCount already).
  Instead we calculate the used pages from the total page count, minus
  everything we account for otherwise. Doing it this way is possible
  without introducing any additional counters, as all the counts to
  subtract are already present (as opposed to some of the ones that
  would be needed for adding the counts up). Fixes #8109.
* Added TODO regarding the problem of not locking any of the counters
  which runs the risk of them getting modified while we haven't yet read
  all of them.
This commit is contained in:
Michael Lotz 2011-11-13 20:42:38 +01:00
parent 3b1791fa15
commit 3733c51d38

View File

@ -4053,13 +4053,9 @@ vm_page_num_unused_pages(void)
void
vm_page_get_stats(system_info *info)
{
// Get free pages count -- not really exact, since we don't know how many
// of the reserved pages have already been allocated, but good citizens
// unreserve chunk-wise as they are allocating the pages, if they have
// reserved a larger quantity.
int32 free = sUnreservedFreePages;
if (free < 0)
free = 0;
// TODO: there's no locking protecting any of the queues or counters here,
// so we run the risk of getting bogus values when evaluating them at
// throughout this function...
// The pages used for the block cache buffers. Those should not be counted
// as used but as cached pages.
@ -4067,11 +4063,25 @@ vm_page_get_stats(system_info *info)
// can't really be freed in a low memory situation.
page_num_t blockCachePages = block_cache_used_memory() / B_PAGE_SIZE;
info->max_pages = sNumPages - sNonExistingPages;
info->used_pages = gMappedPagesCount + sInactivePageQueue.Count()
- blockCachePages;
info->cached_pages = info->max_pages >= free + info->used_pages
? info->max_pages - free - info->used_pages : 0;
// Non-temporary modified pages are special as they represent pages that
// can be written back, so they could be freed if necessary, for us
// basically making them into cached pages with a higher overhead. The
// modified queue count is therefore split into temporary and non-temporary
// counts that are then added to the corresponding number.
page_num_t modifiedNonTemporaryPages
= (sModifiedPageQueue.Count() - sModifiedTemporaryPages);
info->max_pages = vm_page_num_pages();
info->cached_pages = sCachedPageQueue.Count() + modifiedNonTemporaryPages
+ blockCachePages;
// max_pages is composed of:
// active + inactive + unused + wired + modified + cached + free + clear
// So taking out the cached (including modified non-temporary), free and
// clear ones leaves us with all used pages.
info->used_pages = info->max_pages - info->cached_pages
- sFreePageQueue.Count() - sClearPageQueue.Count();
info->page_faults = vm_num_page_faults();
info->ignored_pages = sIgnoredPages;