commit 0c635450a6b0aca09742d8b514562592a3b315e5 Author: Andriy Gapon Date: Thu May 17 20:03:22 2012 +0300 [experiment] device_pager: use a hash table instead of plain list for objects diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c index 99f561f..f0f1bd3 100644 --- a/sys/vm/device_pager.c +++ b/sys/vm/device_pager.c @@ -62,8 +62,6 @@ static void dev_pager_putpages(vm_object_t, vm_page_t *, int, static boolean_t dev_pager_haspage(vm_object_t, vm_pindex_t, int *, int *); -/* list of device pager objects */ -static struct pagerlst dev_pager_object_list; /* protect list manipulation */ static struct mtx dev_pager_mtx; @@ -96,10 +94,68 @@ static struct cdev_pager_ops old_dev_pager_ops = { .cdev_pg_fault = old_dev_pager_fault }; +/* list of device pager objects */ +#define OBJECT_HTABLE_SIZE 256 +static struct pagerlst object_htable[OBJECT_HTABLE_SIZE]; + +static u_int +hash6432shift(uintptr_t key) +{ + key = (~key) + (key << 18); + key = key ^ (key >> 31); + key = key * 21; + key = key ^ (key >> 11); + key = key + (key << 6); + key = key ^ (key >> 22); + return (key); +} + +static int +hash_index(void *handle) +{ + return (hash6432shift((uintptr_t)handle) % OBJECT_HTABLE_SIZE); +} + +static void +object_list_insert(vm_object_t object) +{ + TAILQ_INSERT_TAIL(object_htable + hash_index(object->handle), object, pager_object_list); +} + +static void +object_list_remove(vm_object_t object) +{ + TAILQ_REMOVE(object_htable + hash_index(object->handle), object, pager_object_list); +} + +static vm_object_t +object_list_lookup(void *handle) +{ + struct pagerlst *pglist; + vm_object_t object; + + pglist = object_htable + hash_index(handle); + TAILQ_FOREACH(object, pglist, pager_object_list) { + if (object->handle == handle) { + VM_OBJECT_LOCK(object); + if ((object->flags & OBJ_DEAD) == 0) { + vm_object_reference_locked(object); + VM_OBJECT_UNLOCK(object); + break; + } + VM_OBJECT_UNLOCK(object); + } + } + return (object); +} + static void dev_pager_init() { - TAILQ_INIT(&dev_pager_object_list); + int i; + + for (i = 0; i < OBJECT_HTABLE_SIZE; i++) + TAILQ_INIT(&object_htable[i]); mtx_init(&dev_pager_mtx, "dev_pager list", NULL, MTX_DEF); } @@ -109,7 +165,7 @@ cdev_pager_lookup(void *handle) vm_object_t object; mtx_lock(&dev_pager_mtx); - object = vm_pager_object_lookup(&dev_pager_object_list, handle); + object = object_list_lookup(handle); mtx_unlock(&dev_pager_mtx); return (object); } @@ -142,7 +198,7 @@ cdev_pager_allocate(void *handle, enum obj_type tp, struct cdev_pager_ops *ops, * Look up pager, creating as necessary. */ object1 = NULL; - object = vm_pager_object_lookup(&dev_pager_object_list, handle); + object = object_list_lookup(handle); if (object == NULL) { /* * Allocate object and associate it with the pager. Initialize @@ -157,7 +213,7 @@ cdev_pager_allocate(void *handle, enum obj_type tp, struct cdev_pager_ops *ops, object1->un_pager.devp.ops = ops; TAILQ_INIT(&object1->un_pager.devp.devp_pglist); mtx_lock(&dev_pager_mtx); - object = vm_pager_object_lookup(&dev_pager_object_list, handle); + object = object_list_lookup(handle); if (object != NULL) { /* * We raced with other thread while allocating object. @@ -168,8 +224,7 @@ cdev_pager_allocate(void *handle, enum obj_type tp, struct cdev_pager_ops *ops, object = object1; object1 = NULL; object->handle = handle; - TAILQ_INSERT_TAIL(&dev_pager_object_list, object, - pager_object_list); + object_list_insert(object); KASSERT(object->type == tp, ("Inconsistent device pager type %p %d", object, tp)); } @@ -181,8 +236,7 @@ cdev_pager_allocate(void *handle, enum obj_type tp, struct cdev_pager_ops *ops, if (object1 != NULL) { object1->handle = object1; mtx_lock(&dev_pager_mtx); - TAILQ_INSERT_TAIL(&dev_pager_object_list, object1, - pager_object_list); + object_list_insert(object1); mtx_unlock(&dev_pager_mtx); vm_object_deallocate(object1); } @@ -217,7 +271,7 @@ dev_pager_dealloc(object) object->un_pager.devp.ops->cdev_pg_dtor(object->handle); mtx_lock(&dev_pager_mtx); - TAILQ_REMOVE(&dev_pager_object_list, object, pager_object_list); + object_list_remove(object); mtx_unlock(&dev_pager_mtx); VM_OBJECT_LOCK(object); /*