* Some style cleanup.

* Pulled the code moving the pages out of Merge() into a separate method.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34778 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2009-12-26 21:00:02 +00:00
parent 5458cdeaf5
commit 4566a632c6
2 changed files with 127 additions and 101 deletions

View File

@ -8,6 +8,7 @@
* Distributed under the terms of the NewOS License.
*/
#include "VMAnonymousCache.h"
#include <errno.h>
@ -64,13 +65,14 @@
#define SWAP_BLOCK_SHIFT 5 /* 1 << SWAP_BLOCK_SHIFT == SWAP_BLOCK_PAGES */
#define SWAP_BLOCK_MASK (SWAP_BLOCK_PAGES - 1)
struct swap_file : DoublyLinkedListLinkImpl<swap_file> {
int fd;
struct vnode *vnode;
void *cookie;
struct vnode* vnode;
void* cookie;
swap_addr_t first_slot;
swap_addr_t last_slot;
radix_bitmap *bmp;
radix_bitmap* bmp;
};
struct swap_hash_key {
@ -96,23 +98,23 @@ struct SwapHashTableDefinition {
size_t HashKey(const swap_hash_key& key) const
{
off_t blockIndex = key.page_index >> SWAP_BLOCK_SHIFT;
VMAnonymousCache *cache = key.cache;
return blockIndex ^ (int)(int *)cache;
VMAnonymousCache* cache = key.cache;
return blockIndex ^ (size_t)(int*)cache;
}
size_t Hash(const swap_block *value) const
size_t Hash(const swap_block* value) const
{
return HashKey(value->key);
}
bool Compare(const swap_hash_key& key, const swap_block *value) const
bool Compare(const swap_hash_key& key, const swap_block* value) const
{
return (key.page_index & ~(off_t)SWAP_BLOCK_MASK)
== (value->key.page_index & ~(off_t)SWAP_BLOCK_MASK)
&& key.cache == value->key.cache;
}
swap_block*& GetLink(swap_block *value) const
swap_block*& GetLink(swap_block* value) const
{
return value->hash_link;
}
@ -126,13 +128,13 @@ static rw_lock sSwapHashLock;
static SwapFileList sSwapFileList;
static mutex sSwapFileListLock;
static swap_file *sSwapFileAlloc = NULL; // allocate from here
static swap_file* sSwapFileAlloc = NULL; // allocate from here
static uint32 sSwapFileCount = 0;
static off_t sAvailSwapSpace = 0;
static mutex sAvailSwapSpaceLock;
static object_cache *sSwapBlockCache;
static object_cache* sSwapBlockCache;
#if SWAP_TRACING
@ -288,11 +290,11 @@ swap_slot_alloc(uint32 count)
}
static swap_file *
static swap_file*
find_swap_file(swap_addr_t slotIndex)
{
for (SwapFileList::Iterator it = sSwapFileList.GetIterator();
swap_file *swapFile = it.Next();) {
swap_file* swapFile = it.Next();) {
if (slotIndex >= swapFile->first_slot
&& slotIndex < swapFile->last_slot)
return swapFile;
@ -310,7 +312,7 @@ swap_slot_dealloc(swap_addr_t slotIndex, uint32 count)
return;
mutex_lock(&sSwapFileListLock);
swap_file *swapFile = find_swap_file(slotIndex);
swap_file* swapFile = find_swap_file(slotIndex);
slotIndex -= swapFile->first_slot;
radix_bitmap_dealloc(swapFile->bmp, slotIndex, count);
mutex_unlock(&sSwapFileListLock);
@ -497,8 +499,8 @@ VMAnonymousCache::HasPage(off_t offset)
status_t
VMAnonymousCache::Read(off_t offset, const iovec *vecs, size_t count,
uint32 flags, size_t *_numBytes)
VMAnonymousCache::Read(off_t offset, const iovec* vecs, size_t count,
uint32 flags, size_t* _numBytes)
{
off_t pageIndex = offset >> PAGE_SHIFT;
@ -513,7 +515,7 @@ VMAnonymousCache::Read(off_t offset, const iovec *vecs, size_t count,
T(ReadPage(this, pageIndex, startSlotIndex));
// TODO: Assumes that only one page is read.
swap_file *swapFile = find_swap_file(startSlotIndex);
swap_file* swapFile = find_swap_file(startSlotIndex);
off_t pos = (off_t)(startSlotIndex - swapFile->first_slot)
* B_PAGE_SIZE;
@ -529,8 +531,8 @@ VMAnonymousCache::Read(off_t offset, const iovec *vecs, size_t count,
status_t
VMAnonymousCache::Write(off_t offset, const iovec *vecs, size_t count,
uint32 flags, size_t *_numBytes)
VMAnonymousCache::Write(off_t offset, const iovec* vecs, size_t count,
uint32 flags, size_t* _numBytes)
{
off_t pageIndex = offset >> PAGE_SHIFT;
@ -562,7 +564,7 @@ VMAnonymousCache::Write(off_t offset, const iovec *vecs, size_t count,
for (uint32 i = 0; i < count; i++) {
uint32 pageCount = (vecs[i].iov_len + B_PAGE_SIZE - 1) >> PAGE_SHIFT;
void *vectorBase = vecs[i].iov_base;
void* vectorBase = vecs[i].iov_base;
size_t vectorLength = vecs[i].iov_len;
uint32 n = pageCount;
@ -578,7 +580,7 @@ VMAnonymousCache::Write(off_t offset, const iovec *vecs, size_t count,
T(WritePage(this, pageIndex, slotIndex));
// TODO: Assumes that only one page is written.
swap_file *swapFile = find_swap_file(slotIndex);
swap_file* swapFile = find_swap_file(slotIndex);
off_t pos = (off_t)(slotIndex - swapFile->first_slot) * B_PAGE_SIZE;
@ -602,7 +604,7 @@ VMAnonymousCache::Write(off_t offset, const iovec *vecs, size_t count,
pagesLeft -= n;
if (n != pageCount) {
vectorBase = (void *)((addr_t)vectorBase + n * B_PAGE_SIZE);
vectorBase = (void*)((addr_t)vectorBase + n * B_PAGE_SIZE);
vectorLength -= n * B_PAGE_SIZE;
}
}
@ -683,6 +685,13 @@ VMAnonymousCache::CanWritePage(off_t offset)
}
int32
VMAnonymousCache::MaxPagesPerAsyncWrite() const
{
return 1;
}
status_t
VMAnonymousCache::Fault(struct VMAddressSpace* aspace, off_t offset)
{
@ -744,38 +753,7 @@ VMAnonymousCache::Merge(VMCache* _source)
// Move all not shadowed pages from the source to the consumer cache.
for (VMCachePagesTree::Iterator it = source->pages.GetIterator();
vm_page* page = it.Next();) {
// Note: Removing the current node while iterating through a
// IteratableSplayTree is safe.
vm_page* consumerPage = LookupPage(
(off_t)page->cache_offset << PAGE_SHIFT);
swap_addr_t consumerSwapSlot = _SwapBlockGetAddress(page->cache_offset);
if (consumerPage == NULL && consumerSwapSlot == SWAP_SLOT_NONE) {
// the page is not yet in the consumer cache - move it upwards
source->RemovePage(page);
InsertPage(page, (off_t)page->cache_offset << PAGE_SHIFT);
// If the moved-up page has a swap page associated, we mark it, so
// that the swap page is moved upwards, too. We would lose if the
// page was modified and written to swap, and is now not marked
// modified.
if (source->_SwapBlockGetAddress(page->cache_offset)
!= SWAP_SLOT_NONE) {
page->merge_swap = true;
}
#if DEBUG_PAGE_CACHE_TRANSITIONS
} else {
page->debug_flags = 0;
if (consumerPage->state == PAGE_STATE_BUSY)
page->debug_flags |= 0x1;
if (consumerPage->type == PAGE_TYPE_DUMMY)
page->debug_flags |= 0x2;
page->collided_page = consumerPage;
consumerPage->collided_page = page;
#endif // DEBUG_PAGE_CACHE_TRANSITIONS
}
}
_MergePagesSmallerSource(source);
// Move all not shadowed swap pages from the source to the consumer cache.
@ -844,7 +822,7 @@ VMAnonymousCache::Merge(VMCache* _source)
}
// All source swap pages that have not been freed yet are taken over by
// by the consumer.
// the consumer.
fAllocatedSwapSize += B_PAGE_SIZE * (off_t)sourceSwapBlock->used;
if (sourceSwapBlock->used == 0) {
@ -887,9 +865,9 @@ VMAnonymousCache::_SwapBlockBuild(off_t startPageIndex,
swap_hash_key key = { this, pageIndex };
swap_block *swap = sSwapHashTable.Lookup(key);
swap_block* swap = sSwapHashTable.Lookup(key);
while (swap == NULL) {
swap = (swap_block *)object_cache_alloc(sSwapBlockCache,
swap = (swap_block*)object_cache_alloc(sSwapBlockCache,
CACHE_DONT_SLEEP);
if (swap == NULL) {
// Wait a short time until memory is available again.
@ -929,7 +907,7 @@ VMAnonymousCache::_SwapBlockFree(off_t startPageIndex, uint32 count)
for (uint32 i = 0, j = 0; i < count; i += j) {
off_t pageIndex = startPageIndex + i;
swap_hash_key key = { this, pageIndex };
swap_block *swap = sSwapHashTable.Lookup(key);
swap_block* swap = sSwapHashTable.Lookup(key);
ASSERT(swap != NULL);
@ -954,7 +932,7 @@ VMAnonymousCache::_SwapBlockGetAddress(off_t pageIndex)
ReadLocker locker(sSwapHashLock);
swap_hash_key key = { this, pageIndex };
swap_block *swap = sSwapHashTable.Lookup(key);
swap_block* swap = sSwapHashTable.Lookup(key);
swap_addr_t slotIndex = SWAP_SLOT_NONE;
if (swap != NULL) {
@ -1028,11 +1006,49 @@ VMAnonymousCache::_Commit(off_t size)
}
void
VMAnonymousCache::_MergePagesSmallerSource(VMAnonymousCache* source)
{
for (VMCachePagesTree::Iterator it = source->pages.GetIterator();
vm_page* page = it.Next();) {
// Note: Removing the current node while iterating through a
// IteratableSplayTree is safe.
vm_page* consumerPage = LookupPage(
(off_t)page->cache_offset << PAGE_SHIFT);
swap_addr_t consumerSwapSlot = _SwapBlockGetAddress(page->cache_offset);
if (consumerPage == NULL && consumerSwapSlot == SWAP_SLOT_NONE) {
// the page is not yet in the consumer cache - move it upwards
source->RemovePage(page);
InsertPage(page, (off_t)page->cache_offset << PAGE_SHIFT);
// If the moved-up page has a swap page associated, we mark it, so
// that the swap page is moved upwards, too. We would lose if the
// page was modified and written to swap, and is now not marked
// modified.
if (source->_SwapBlockGetAddress(page->cache_offset)
!= SWAP_SLOT_NONE) {
page->merge_swap = true;
}
#if DEBUG_PAGE_CACHE_TRANSITIONS
} else {
page->debug_flags = 0;
if (consumerPage->state == PAGE_STATE_BUSY)
page->debug_flags |= 0x1;
if (consumerPage->type == PAGE_TYPE_DUMMY)
page->debug_flags |= 0x2;
page->collided_page = consumerPage;
consumerPage->collided_page = page;
#endif // DEBUG_PAGE_CACHE_TRANSITIONS
}
}
}
// #pragma mark -
status_t
swap_file_add(const char *path)
swap_file_add(const char* path)
{
// open the file
int fd = open(path, O_RDWR | O_NOCACHE, S_IRUSR | S_IWUSR);
@ -1060,14 +1076,14 @@ swap_file_add(const char *path)
file_descriptor* descriptor = get_fd(get_current_io_context(true), fd);
put_fd(descriptor);
vnode *node = fd_vnode(descriptor);
vnode* node = fd_vnode(descriptor);
if (node == NULL) {
close(fd);
return B_BAD_VALUE;
}
// do the allocations and prepare the swap_file structure
swap_file *swap = (swap_file *)malloc(sizeof(swap_file));
swap_file* swap = (swap_file*)malloc(sizeof(swap_file));
if (swap == NULL) {
close(fd);
return B_NO_MEMORY;
@ -1109,16 +1125,16 @@ swap_file_add(const char *path)
status_t
swap_file_delete(const char *path)
swap_file_delete(const char* path)
{
vnode *node = NULL;
vnode* node = NULL;
status_t status = vfs_get_vnode_from_path(path, true, &node);
if (status != B_OK)
return status;
MutexLocker locker(sSwapFileListLock);
swap_file *swapFile = NULL;
swap_file* swapFile = NULL;
for (SwapFileList::Iterator it = sSwapFileList.GetIterator();
(swapFile = it.Next()) != NULL;) {
if (swapFile->vnode == node)
@ -1206,12 +1222,12 @@ swap_init_post_modules()
off_t size = 0;
void *settings = load_driver_settings("virtual_memory");
void* settings = load_driver_settings("virtual_memory");
if (settings != NULL) {
if (!get_driver_boolean_parameter(settings, "vm", false, false))
return;
const char *string = get_driver_parameter(settings, "swap_size", NULL,
const char* string = get_driver_parameter(settings, "swap_size", NULL,
NULL);
size = string ? atoll(string) : 0;
@ -1247,9 +1263,9 @@ swap_init_post_modules()
//! Used by page daemon to free swap space.
bool
swap_free_page_swap_space(vm_page *page)
swap_free_page_swap_space(vm_page* page)
{
VMAnonymousCache *cache = dynamic_cast<VMAnonymousCache *>(page->cache);
VMAnonymousCache* cache = dynamic_cast<VMAnonymousCache*>(page->cache);
if (cache == NULL)
return false;
@ -1283,7 +1299,7 @@ swap_total_swap_pages()
uint32 totalSwapSlots = 0;
for (SwapFileList::Iterator it = sSwapFileList.GetIterator();
swap_file *swapFile = it.Next();)
swap_file* swapFile = it.Next();)
totalSwapSlots += swapFile->last_slot - swapFile->first_slot;
mutex_unlock(&sSwapFileListLock);
@ -1294,7 +1310,7 @@ swap_total_swap_pages()
#endif // ENABLE_SWAP_SUPPORT
void
swap_get_info(struct system_memory_info *info)
swap_get_info(struct system_memory_info* info)
{
#if ENABLE_SWAP_SUPPORT
info->max_swap_space = (uint64)swap_total_swap_pages() * B_PAGE_SIZE;

View File

@ -23,7 +23,7 @@ struct system_memory_info;
extern "C" {
void swap_init(void);
void swap_init_post_modules(void);
bool swap_free_page_swap_space(vm_page *page);
bool swap_free_page_swap_space(vm_page* page);
uint32 swap_available_pages(void);
uint32 swap_total_swap_pages(void);
}
@ -31,53 +31,63 @@ extern "C" {
class VMAnonymousCache : public VMCache {
public:
virtual ~VMAnonymousCache();
virtual ~VMAnonymousCache();
status_t Init(bool canOvercommit, int32 numPrecommittedPages,
int32 numGuardPages);
status_t Init(bool canOvercommit,
int32 numPrecommittedPages,
int32 numGuardPages);
virtual status_t Commit(off_t size);
virtual bool HasPage(off_t offset);
virtual status_t Commit(off_t size);
virtual bool HasPage(off_t offset);
virtual status_t Read(off_t offset, const iovec *vecs, size_t count,
uint32 flags, size_t *_numBytes);
virtual status_t Write(off_t offset, const iovec *vecs, size_t count,
uint32 flags, size_t *_numBytes);
virtual status_t WriteAsync(off_t offset, const iovec* vecs,
size_t count, size_t numBytes, uint32 flags,
AsyncIOCallback* callback);
virtual bool CanWritePage(off_t offset);
virtual status_t Read(off_t offset, const iovec* vecs,
size_t count, uint32 flags,
size_t* _numBytes);
virtual status_t Write(off_t offset, const iovec* vecs,
size_t count, uint32 flags,
size_t* _numBytes);
virtual status_t WriteAsync(off_t offset, const iovec* vecs,
size_t count, size_t numBytes, uint32 flags,
AsyncIOCallback* callback);
virtual bool CanWritePage(off_t offset);
virtual int32 MaxPagesPerAsyncWrite() const
{ return 1; }
virtual int32 MaxPagesPerAsyncWrite() const;
virtual status_t Fault(struct VMAddressSpace* aspace, off_t offset);
virtual status_t Fault(struct VMAddressSpace* aspace,
off_t offset);
virtual void Merge(VMCache* source);
virtual void Merge(VMCache* source);
private:
class WriteCallback;
friend class WriteCallback;
void _SwapBlockBuild(off_t pageIndex,
swap_addr_t slotIndex, uint32 count);
void _SwapBlockFree(off_t pageIndex, uint32 count);
swap_addr_t _SwapBlockGetAddress(off_t pageIndex);
status_t _Commit(off_t size);
void _SwapBlockBuild(off_t pageIndex,
swap_addr_t slotIndex, uint32 count);
void _SwapBlockFree(off_t pageIndex, uint32 count);
swap_addr_t _SwapBlockGetAddress(off_t pageIndex);
status_t _Commit(off_t size);
void _MergePagesSmallerSource(
VMAnonymousCache* source);
void _MergePagesSmallerConsumer(
VMAnonymousCache* source);
private:
friend bool swap_free_page_swap_space(vm_page *page);
friend bool swap_free_page_swap_space(vm_page* page);
bool fCanOvercommit;
bool fHasPrecommitted;
uint8 fPrecommittedPages;
int32 fGuardedSize;
off_t fCommittedSwapSize;
off_t fAllocatedSwapSize;
bool fCanOvercommit;
bool fHasPrecommitted;
uint8 fPrecommittedPages;
int32 fGuardedSize;
off_t fCommittedSwapSize;
off_t fAllocatedSwapSize;
};
#endif // ENABLE_SWAP_SUPPORT
extern "C" void swap_get_info(struct system_memory_info *info);
extern "C" void swap_get_info(struct system_memory_info* info);
#endif /* _KERNEL_VM_STORE_ANONYMOUS_H */