* 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:
@@ -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);
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user