* Moved the incrementing/decrementing of vm_page::wired_count into

dedicated functions.
* Introduced gMappedPagesCount variable which counts the total number of
  physical pages that are mapped.
* Added vm_page_get_stats() which fills in the memory related part of
  the system_info structure. Used and cached pages are computed
  differently, now. The "available" (== not committed) memory is no
  longer used for the computation as it doesn't say anything about the
  actually used/free pages (with swap support enabled it is even
  less meaningful, since we first commit swap space when possible).
  We do also consider the memory used by the block cache as cached
  pages, now. All in all these changes should fix the memory statistics
  reported by get_system_info(), IOW bug #2574.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26837 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2008-08-06 00:28:28 +00:00
parent c79e66abb7
commit 8d12bd1370
4 changed files with 74 additions and 18 deletions
+2
View File
@@ -14,6 +14,7 @@
struct kernel_args;
extern int32 gMappedPagesCount;
#ifdef __cplusplus
extern "C" {
@@ -34,6 +35,7 @@ void vm_page_requeue(struct vm_page *page, bool tail);
size_t vm_page_num_pages(void);
size_t vm_page_num_free_pages(void);
size_t vm_page_num_available_pages(void);
void vm_page_get_stats(system_info *info);
status_t vm_page_write_modified_page_range(struct VMCache *cache,
uint32 firstPage, uint32 endPage);
+1 -4
View File
@@ -77,11 +77,8 @@ _get_system_info(system_info *info, size_t size)
for (int32 i = 0; i < info->cpu_count; i++)
info->cpu_infos[i].active_time = cpu_get_active_time(i);
vm_page_get_stats(info);
// TODO: Add page_faults
info->max_pages = vm_page_num_pages();
info->used_pages = info->max_pages - vm_page_num_available_pages();
info->cached_pages = info->max_pages - vm_page_num_free_pages()
- info->used_pages;
info->used_threads = thread_used_threads();
info->max_threads = thread_max_threads();
+43 -14
View File
@@ -1329,6 +1329,32 @@ cut_area(vm_address_space* addressSpace, vm_area* area, addr_t address,
}
static inline void
increment_page_wired_count(vm_page* page)
{
// TODO: needs to be atomic on all platforms!
// ... but at least the check isn't. Consequently we should hold
// sMappingLock, which would allows us to even avoid atomic_add() on
// gMappedPagesCount.
if (page->wired_count++ == 0) {
if (page->mappings.IsEmpty())
atomic_add(&gMappedPagesCount, 1);
}
}
static inline void
decrement_page_wired_count(vm_page* page)
{
if (--page->wired_count == 0) {
// TODO: needs to be atomic on all platforms!
// See above!
if (page->mappings.IsEmpty())
atomic_add(&gMappedPagesCount, -1);
}
}
/*! Deletes all areas in the given address range.
The address space must be write-locked.
*/
@@ -1802,8 +1828,7 @@ vm_create_anonymous_area(team_id team, const char *name, void **address,
physicalAddress);
}
page->wired_count++;
// TODO: needs to be atomic on all platforms!
increment_page_wired_count(page);
vm_page_set_state(page, PAGE_STATE_WIRED);
cache->InsertPage(page, offset);
}
@@ -1835,8 +1860,7 @@ vm_create_anonymous_area(team_id team, const char *name, void **address,
if (status < B_OK)
panic("couldn't map physical page in page run\n");
page->wired_count++;
// TODO: needs to be atomic on all platforms!
increment_page_wired_count(page);
vm_page_set_state(page, PAGE_STATE_WIRED);
cache->InsertPage(page, offset);
}
@@ -2740,6 +2764,9 @@ vm_remove_all_page_mappings(vm_page *page, uint32 *_flags)
accumulatedFlags |= flags;
}
if (page->wired_count == 0)
atomic_add(&gMappedPagesCount, -1);
locker.Unlock();
// free now unused mappings
@@ -2778,8 +2805,7 @@ vm_unmap_pages(vm_area *area, addr_t base, size_t size, bool preserveModified)
physicalAddress);
}
page->wired_count--;
// TODO: needs to be atomic on all platforms!
decrement_page_wired_count(page);
}
}
@@ -2828,9 +2854,12 @@ vm_unmap_pages(vm_area *area, addr_t base, size_t size, bool preserveModified)
|| page->cache_offset >= endOffset)
continue;
mapping->page->mappings.Remove(mapping);
page->mappings.Remove(mapping);
iterator.Remove();
if (page->mappings.IsEmpty() && page->wired_count == 0)
atomic_add(&gMappedPagesCount, -1);
queue.Add(mapping);
}
@@ -2868,12 +2897,14 @@ vm_map_page(vm_area *area, vm_page *page, addr_t address, uint32 protection)
map->ops->unlock(map);
if (area->wiring != B_NO_LOCK) {
page->wired_count++;
// TODO: needs to be atomic on all platforms!
increment_page_wired_count(page);
} else {
// insert mapping into lists
MutexLocker locker(sMappingLock);
if (page->mappings.IsEmpty() && page->wired_count == 0)
atomic_add(&gMappedPagesCount, 1);
page->mappings.Add(mapping);
area->mappings.Add(mapping);
}
@@ -5063,8 +5094,7 @@ lock_memory_etc(team_id team, void *address, size_t numBytes, uint32 flags)
if (page == NULL)
panic("couldn't lookup physical page just allocated\n");
page->wired_count++;
// TODO: needs to be atomic on all platforms!
increment_page_wired_count(page);
continue;
}
}
@@ -5098,7 +5128,7 @@ lock_memory_etc(team_id team, void *address, size_t numBytes, uint32 flags)
if (page == NULL)
panic("couldn't lookup physical page");
page->wired_count++;
increment_page_wired_count(page);
// TODO: needs to be atomic on all platforms!
}
@@ -5163,8 +5193,7 @@ unlock_memory_etc(team_id team, void *address, size_t numBytes, uint32 flags)
if (page == NULL)
panic("couldn't lookup physical page");
page->wired_count--;
// TODO: needs to be atomic on all platforms!
decrement_page_wired_count(page);
}
out:
+28
View File
@@ -15,6 +15,7 @@
#include <arch/cpu.h>
#include <arch/vm_translation_map.h>
#include <block_cache.h>
#include <boot/kernel_args.h>
#include <condition_variable.h>
#include <kernel.h>
@@ -47,6 +48,8 @@ typedef struct page_queue {
uint32 count;
} page_queue;
int32 gMappedPagesCount;
static page_queue sFreePageQueue;
static page_queue sClearPageQueue;
static page_queue sModifiedPageQueue;
@@ -1916,3 +1919,28 @@ vm_page_num_free_pages(void)
return count - reservedPages;
}
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.
page_num_t reserved = sReservedPages;
page_num_t free = free_page_queue_count();
free = free > reserved ? free - reserved : 0;
// The pages used for the block cache buffers. Those should not be counted
// as used but as cached pages.
// TODO: We should subtract the blocks that are in use ATM, since those
// 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;
info->used_pages = gMappedPagesCount - blockCachePages;
info->cached_pages = sNumPages >= free + info->used_pages
? sNumPages - free - info->used_pages : 0;
// TODO: We don't consider pages used for page directories/tables yet.
}