Cleanup, no functional change.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8910 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+116
-83
@@ -18,8 +18,17 @@
|
|||||||
#include <arch/cpu.h>
|
#include <arch/cpu.h>
|
||||||
#include <Errors.h>
|
#include <Errors.h>
|
||||||
|
|
||||||
|
//#define TRACE_VM_CACHE
|
||||||
|
#ifdef TRACE_VM_CACHE
|
||||||
|
# define TRACE(x) dprintf x
|
||||||
|
#else
|
||||||
|
# define TRACE(x) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* hash table of pages keyed by cache they're in and offset */
|
/* hash table of pages keyed by cache they're in and offset */
|
||||||
#define PAGE_TABLE_SIZE 1024 /* make this dynamic */
|
#define PAGE_TABLE_SIZE 1024 /* make this dynamic */
|
||||||
|
|
||||||
static void *page_cache_table;
|
static void *page_cache_table;
|
||||||
static spinlock page_cache_table_lock;
|
static spinlock page_cache_table_lock;
|
||||||
|
|
||||||
@@ -28,20 +37,21 @@ struct page_lookup_key {
|
|||||||
vm_cache_ref *ref;
|
vm_cache_ref *ref;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int page_compare_func(void *_p, const void *_key)
|
|
||||||
|
static int
|
||||||
|
page_compare_func(void *_p, const void *_key)
|
||||||
{
|
{
|
||||||
vm_page *p = _p;
|
vm_page *p = _p;
|
||||||
const struct page_lookup_key *key = _key;
|
const struct page_lookup_key *key = _key;
|
||||||
|
|
||||||
// dprintf("page_compare_func: p 0x%x, key 0x%x\n", p, key);
|
TRACE(("page_compare_func: p 0x%x, key 0x%x\n", p, key));
|
||||||
|
|
||||||
if(p->cache_ref == key->ref && p->offset == key->offset)
|
if (p->cache_ref == key->ref && p->offset == key->offset)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define HASH(offset, ref) ((unsigned int)(offset >> 12) ^ ((unsigned int)(ref)>>4))
|
|
||||||
|
|
||||||
static uint32
|
static uint32
|
||||||
page_hash_func(void *_p, const void *_key, uint32 range)
|
page_hash_func(void *_p, const void *_key, uint32 range)
|
||||||
@@ -54,40 +64,44 @@ page_hash_func(void *_p, const void *_key, uint32 range)
|
|||||||
else
|
else
|
||||||
dprintf("page_hash_func: p 0x%x, key 0x%x, HASH = 0x%x\n", p, key, HASH(key->offset, key->ref) % range);
|
dprintf("page_hash_func: p 0x%x, key 0x%x, HASH = 0x%x\n", p, key, HASH(key->offset, key->ref) % range);
|
||||||
#endif
|
#endif
|
||||||
if(p)
|
#define HASH(offset, ref) ((unsigned int)(offset >> 12) ^ ((unsigned int)(ref)>>4))
|
||||||
|
|
||||||
|
if (p)
|
||||||
return HASH(p->offset, p->cache_ref) % range;
|
return HASH(p->offset, p->cache_ref) % range;
|
||||||
else
|
|
||||||
return HASH(key->offset, key->ref) % range;
|
return HASH(key->offset, key->ref) % range;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vm_cache_init(kernel_args *ka)
|
|
||||||
|
int
|
||||||
|
vm_cache_init(kernel_args *ka)
|
||||||
{
|
{
|
||||||
vm_page p;
|
vm_page p;
|
||||||
|
|
||||||
page_cache_table = hash_init(PAGE_TABLE_SIZE,
|
page_cache_table = hash_init(PAGE_TABLE_SIZE, (int)&p.hash_next - (int)&p,
|
||||||
(int)&p.hash_next - (int)&p,
|
&page_compare_func, &page_hash_func);
|
||||||
&page_compare_func,
|
if (!page_cache_table)
|
||||||
&page_hash_func);
|
|
||||||
if(!page_cache_table)
|
|
||||||
panic("vm_cache_init: cannot allocate memory for page cache hash table\n");
|
panic("vm_cache_init: cannot allocate memory for page cache hash table\n");
|
||||||
page_cache_table_lock = 0;
|
page_cache_table_lock = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
vm_cache *vm_cache_create(vm_store *store)
|
|
||||||
|
vm_cache *
|
||||||
|
vm_cache_create(vm_store *store)
|
||||||
{
|
{
|
||||||
vm_cache *cache;
|
vm_cache *cache;
|
||||||
|
|
||||||
cache = malloc(sizeof(vm_cache));
|
cache = malloc(sizeof(vm_cache));
|
||||||
if(cache == NULL)
|
if (cache == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
cache->page_list = NULL;
|
cache->page_list = NULL;
|
||||||
cache->ref = NULL;
|
cache->ref = NULL;
|
||||||
cache->source = NULL;
|
cache->source = NULL;
|
||||||
cache->store = store;
|
cache->store = store;
|
||||||
if(store != NULL)
|
if (store != NULL)
|
||||||
store->cache = cache;
|
store->cache = cache;
|
||||||
cache->virtual_size = 0;
|
cache->virtual_size = 0;
|
||||||
cache->temporary = 0;
|
cache->temporary = 0;
|
||||||
@@ -96,12 +110,14 @@ vm_cache *vm_cache_create(vm_store *store)
|
|||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
vm_cache_ref *vm_cache_ref_create(vm_cache *cache)
|
|
||||||
|
vm_cache_ref *
|
||||||
|
vm_cache_ref_create(vm_cache *cache)
|
||||||
{
|
{
|
||||||
vm_cache_ref *ref;
|
vm_cache_ref *ref;
|
||||||
|
|
||||||
ref = malloc(sizeof(vm_cache_ref));
|
ref = malloc(sizeof(vm_cache_ref));
|
||||||
if(ref == NULL)
|
if (ref == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ref->cache = cache;
|
ref->cache = cache;
|
||||||
@@ -113,73 +129,82 @@ vm_cache_ref *vm_cache_ref_create(vm_cache *cache)
|
|||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_cache_acquire_ref(vm_cache_ref *cache_ref, bool acquire_store_ref)
|
|
||||||
|
void
|
||||||
|
vm_cache_acquire_ref(vm_cache_ref *cache_ref, bool acquire_store_ref)
|
||||||
{
|
{
|
||||||
// dprintf("vm_cache_acquire_ref: cache_ref 0x%x, ref will be %d\n", cache_ref, cache_ref->ref_count+1);
|
// dprintf("vm_cache_acquire_ref: cache_ref 0x%x, ref will be %d\n", cache_ref, cache_ref->ref_count+1);
|
||||||
|
|
||||||
if(cache_ref == NULL)
|
if (cache_ref == NULL)
|
||||||
panic("vm_cache_acquire_ref: passed NULL\n");
|
panic("vm_cache_acquire_ref: passed NULL\n");
|
||||||
if(acquire_store_ref && cache_ref->cache->store->ops->acquire_ref) {
|
|
||||||
|
if (acquire_store_ref && cache_ref->cache->store->ops->acquire_ref)
|
||||||
cache_ref->cache->store->ops->acquire_ref(cache_ref->cache->store);
|
cache_ref->cache->store->ops->acquire_ref(cache_ref->cache->store);
|
||||||
}
|
|
||||||
atomic_add(&cache_ref->ref_count, 1);
|
atomic_add(&cache_ref->ref_count, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_cache_release_ref(vm_cache_ref *cache_ref)
|
|
||||||
|
void
|
||||||
|
vm_cache_release_ref(vm_cache_ref *cache_ref)
|
||||||
{
|
{
|
||||||
|
off_t store_committed_size = 0;
|
||||||
vm_page *page;
|
vm_page *page;
|
||||||
|
|
||||||
// dprintf("vm_cache_release_ref: cache_ref 0x%x, ref will be %d\n", cache_ref, cache_ref->ref_count-1);
|
TRACE(("vm_cache_release_ref: cache_ref 0x%x, ref will be %d\n", cache_ref, cache_ref->ref_count - 1));
|
||||||
|
|
||||||
if(cache_ref == NULL)
|
if (cache_ref == NULL)
|
||||||
panic("vm_cache_release_ref: passed NULL\n");
|
panic("vm_cache_release_ref: passed NULL\n");
|
||||||
if(atomic_add(&cache_ref->ref_count, -1) == 1) {
|
|
||||||
// delete this cache
|
|
||||||
// delete the cache's backing store, if it has one
|
|
||||||
off_t store_committed_size = 0;
|
|
||||||
if(cache_ref->cache->store) {
|
|
||||||
store_committed_size = cache_ref->cache->store->committed_size;
|
|
||||||
(*cache_ref->cache->store->ops->destroy)(cache_ref->cache->store);
|
|
||||||
}
|
|
||||||
|
|
||||||
// free all of the pages in the cache
|
if (atomic_add(&cache_ref->ref_count, -1) != 1) {
|
||||||
page = cache_ref->cache->page_list;
|
if (cache_ref->cache->store->ops->release_ref)
|
||||||
while(page) {
|
cache_ref->cache->store->ops->release_ref(cache_ref->cache->store);
|
||||||
vm_page *old_page = page;
|
|
||||||
int state;
|
|
||||||
|
|
||||||
page = page->cache_next;
|
|
||||||
|
|
||||||
// remove it from the hash table
|
|
||||||
state = disable_interrupts();
|
|
||||||
acquire_spinlock(&page_cache_table_lock);
|
|
||||||
|
|
||||||
hash_remove(page_cache_table, old_page);
|
|
||||||
|
|
||||||
release_spinlock(&page_cache_table_lock);
|
|
||||||
restore_interrupts(state);
|
|
||||||
|
|
||||||
// dprintf("vm_cache_release_ref: freeing page 0x%x\n", old_page->ppn);
|
|
||||||
vm_page_set_state(old_page, PAGE_STATE_FREE);
|
|
||||||
}
|
|
||||||
vm_increase_max_commit(cache_ref->cache->virtual_size - store_committed_size);
|
|
||||||
|
|
||||||
// remove the ref to the source
|
|
||||||
if(cache_ref->cache->source)
|
|
||||||
vm_cache_release_ref(cache_ref->cache->source->ref);
|
|
||||||
|
|
||||||
mutex_destroy(&cache_ref->lock);
|
|
||||||
free(cache_ref->cache);
|
|
||||||
free(cache_ref);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(cache_ref->cache->store->ops->release_ref) {
|
|
||||||
cache_ref->cache->store->ops->release_ref(cache_ref->cache->store);
|
// delete this cache
|
||||||
|
|
||||||
|
// delete the cache's backing store, if it has one
|
||||||
|
if (cache_ref->cache->store) {
|
||||||
|
store_committed_size = cache_ref->cache->store->committed_size;
|
||||||
|
(*cache_ref->cache->store->ops->destroy)(cache_ref->cache->store);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// free all of the pages in the cache
|
||||||
|
page = cache_ref->cache->page_list;
|
||||||
|
while (page) {
|
||||||
|
vm_page *oldPage = page;
|
||||||
|
int state;
|
||||||
|
|
||||||
|
page = page->cache_next;
|
||||||
|
|
||||||
|
// remove it from the hash table
|
||||||
|
state = disable_interrupts();
|
||||||
|
acquire_spinlock(&page_cache_table_lock);
|
||||||
|
|
||||||
|
hash_remove(page_cache_table, oldPage);
|
||||||
|
|
||||||
|
release_spinlock(&page_cache_table_lock);
|
||||||
|
restore_interrupts(state);
|
||||||
|
|
||||||
|
TRACE(("vm_cache_release_ref: freeing page 0x%x\n", oldPage->ppn));
|
||||||
|
vm_page_set_state(oldPage, PAGE_STATE_FREE);
|
||||||
|
}
|
||||||
|
vm_increase_max_commit(cache_ref->cache->virtual_size - store_committed_size);
|
||||||
|
|
||||||
|
// remove the ref to the source
|
||||||
|
if (cache_ref->cache->source)
|
||||||
|
vm_cache_release_ref(cache_ref->cache->source->ref);
|
||||||
|
|
||||||
|
mutex_destroy(&cache_ref->lock);
|
||||||
|
free(cache_ref->cache);
|
||||||
|
free(cache_ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
vm_page *vm_cache_lookup_page(vm_cache_ref *cache_ref, off_t offset)
|
|
||||||
|
vm_page *
|
||||||
|
vm_cache_lookup_page(vm_cache_ref *cache_ref, off_t offset)
|
||||||
{
|
{
|
||||||
vm_page *page;
|
vm_page *page;
|
||||||
int state;
|
int state;
|
||||||
@@ -199,17 +224,19 @@ vm_page *vm_cache_lookup_page(vm_cache_ref *cache_ref, off_t offset)
|
|||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_cache_insert_page(vm_cache_ref *cache_ref, vm_page *page, off_t offset)
|
|
||||||
|
void
|
||||||
|
vm_cache_insert_page(vm_cache_ref *cache_ref, vm_page *page, off_t offset)
|
||||||
{
|
{
|
||||||
int state;
|
int state;
|
||||||
|
|
||||||
// dprintf("vm_cache_insert_page: cache 0x%x, page 0x%x, offset 0x%x 0x%x\n", cache_ref, page, offset);
|
TRACE(("vm_cache_insert_page: cache 0x%x, page 0x%x, offset 0x%x 0x%x\n", cache_ref, page, offset));
|
||||||
|
|
||||||
page->offset = offset;
|
page->offset = offset;
|
||||||
|
|
||||||
if(cache_ref->cache->page_list != NULL) {
|
if (cache_ref->cache->page_list != NULL)
|
||||||
cache_ref->cache->page_list->cache_prev = page;
|
cache_ref->cache->page_list->cache_prev = page;
|
||||||
}
|
|
||||||
page->cache_next = cache_ref->cache->page_list;
|
page->cache_next = cache_ref->cache->page_list;
|
||||||
page->cache_prev = NULL;
|
page->cache_prev = NULL;
|
||||||
cache_ref->cache->page_list = page;
|
cache_ref->cache->page_list = page;
|
||||||
@@ -226,11 +253,13 @@ void vm_cache_insert_page(vm_cache_ref *cache_ref, vm_page *page, off_t offset)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_cache_remove_page(vm_cache_ref *cache_ref, vm_page *page)
|
|
||||||
|
void
|
||||||
|
vm_cache_remove_page(vm_cache_ref *cache_ref, vm_page *page)
|
||||||
{
|
{
|
||||||
int state;
|
int state;
|
||||||
|
|
||||||
// dprintf("vm_cache_remove_page: cache 0x%x, page 0x%x\n", cache_ref, page);
|
TRACE(("vm_cache_remove_page: cache 0x%x, page 0x%x\n", cache_ref, page));
|
||||||
|
|
||||||
state = disable_interrupts();
|
state = disable_interrupts();
|
||||||
acquire_spinlock(&page_cache_table_lock);
|
acquire_spinlock(&page_cache_table_lock);
|
||||||
@@ -240,25 +269,27 @@ void vm_cache_remove_page(vm_cache_ref *cache_ref, vm_page *page)
|
|||||||
release_spinlock(&page_cache_table_lock);
|
release_spinlock(&page_cache_table_lock);
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
|
|
||||||
if(cache_ref->cache->page_list == page) {
|
if (cache_ref->cache->page_list == page) {
|
||||||
if(page->cache_next != NULL)
|
if (page->cache_next != NULL)
|
||||||
page->cache_next->cache_prev = NULL;
|
page->cache_next->cache_prev = NULL;
|
||||||
cache_ref->cache->page_list = page->cache_next;
|
cache_ref->cache->page_list = page->cache_next;
|
||||||
} else {
|
} else {
|
||||||
if(page->cache_prev != NULL)
|
if (page->cache_prev != NULL)
|
||||||
page->cache_prev->cache_next = page->cache_next;
|
page->cache_prev->cache_next = page->cache_next;
|
||||||
if(page->cache_next != NULL)
|
if (page->cache_next != NULL)
|
||||||
page->cache_next->cache_prev = page->cache_prev;
|
page->cache_next->cache_prev = page->cache_prev;
|
||||||
}
|
}
|
||||||
page->cache_ref = NULL;
|
page->cache_ref = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vm_cache_insert_region(vm_cache_ref *cache_ref, vm_region *region)
|
|
||||||
|
int
|
||||||
|
vm_cache_insert_region(vm_cache_ref *cache_ref, vm_region *region)
|
||||||
{
|
{
|
||||||
mutex_lock(&cache_ref->lock);
|
mutex_lock(&cache_ref->lock);
|
||||||
|
|
||||||
region->cache_next = cache_ref->region_list;
|
region->cache_next = cache_ref->region_list;
|
||||||
if(region->cache_next)
|
if (region->cache_next)
|
||||||
region->cache_next->cache_prev = region;
|
region->cache_next->cache_prev = region;
|
||||||
region->cache_prev = NULL;
|
region->cache_prev = NULL;
|
||||||
cache_ref->region_list = region;
|
cache_ref->region_list = region;
|
||||||
@@ -267,15 +298,17 @@ int vm_cache_insert_region(vm_cache_ref *cache_ref, vm_region *region)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vm_cache_remove_region(vm_cache_ref *cache_ref, vm_region *region)
|
|
||||||
|
int
|
||||||
|
vm_cache_remove_region(vm_cache_ref *cache_ref, vm_region *region)
|
||||||
{
|
{
|
||||||
mutex_lock(&cache_ref->lock);
|
mutex_lock(&cache_ref->lock);
|
||||||
|
|
||||||
if(region->cache_prev)
|
if (region->cache_prev)
|
||||||
region->cache_prev->cache_next = region->cache_next;
|
region->cache_prev->cache_next = region->cache_next;
|
||||||
if(region->cache_next)
|
if (region->cache_next)
|
||||||
region->cache_next->cache_prev = region->cache_prev;
|
region->cache_next->cache_prev = region->cache_prev;
|
||||||
if(cache_ref->region_list == region)
|
if (cache_ref->region_list == region)
|
||||||
cache_ref->region_list = region->cache_next;
|
cache_ref->region_list = region->cache_next;
|
||||||
|
|
||||||
mutex_unlock(&cache_ref->lock);
|
mutex_unlock(&cache_ref->lock);
|
||||||
|
|||||||
Reference in New Issue
Block a user