* rights to redistribute these changes.
*
* $FreeBSD: src/sys/vm/vm_object.c,v 1.171.2.8 2003/05/26 19:17:56 alc Exp $
- * $DragonFly: src/sys/vm/vm_object.c,v 1.33 2008/05/09 07:24:48 dillon Exp $
*/
/*
#include <sys/mount.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
+#include <sys/refcount.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
static void vm_object_qcollapse(vm_object_t object);
static int vm_object_page_collect_flush(vm_object_t object, vm_page_t p,
int pagerflags);
+static void vm_object_lock_init(vm_object_t);
+static void vm_object_hold_wake(vm_object_t);
+static void vm_object_hold_wait(vm_object_t);
+
/*
* Virtual memory objects maintain the actual data
static int next_index;
static vm_zone_t obj_zone;
static struct vm_zone obj_zone_store;
-static int object_hash_rand;
#define VM_OBJECTS_INIT 256
static struct vm_object vm_objects_init[VM_OBJECTS_INIT];
object->type = type;
object->size = size;
object->ref_count = 1;
+ object->hold_count = 0;
object->flags = 0;
if ((object->type == OBJT_DEFAULT) || (object->type == OBJT_SWAP))
vm_object_set_flag(object, OBJ_ONEMAPPING);
object->handle = NULL;
object->backing_object = NULL;
object->backing_object_offset = (vm_ooffset_t) 0;
- /*
- * Try to generate a number that will spread objects out in the
- * hash table. We 'wipe' new objects across the hash in 128 page
- * increments plus 1 more to offset it a little more by the time
- * it wraps around.
- */
- object->hash_rand = object_hash_rand - 129;
object->generation++;
object->swblock_count = 0;
RB_INIT(&object->swblock_root);
- lwkt_token_init(&object->tok, "vmobjtk");
+ vm_object_lock_init(object);
lwkt_gettoken(&vmobj_token);
TAILQ_INSERT_TAIL(&vm_object_list, object, object_list);
vm_object_count++;
- object_hash_rand = object->hash_rand;
lwkt_reltoken(&vmobj_token);
}
{
if (object) {
ASSERT_LWKT_TOKEN_HELD(&vmobj_token);
- vm_object_lock(object);
object->ref_count++;
if (object->type == OBJT_VNODE) {
vref(object->handle);
/* XXX what if the vnode is being destroyed? */
}
- vm_object_unlock(object);
}
}
/*
* Wait for the pageout daemon to be done with the object
*/
- vm_object_pip_wait(object, "objtrm");
+ vm_object_pip_wait(object, "objtrm1");
KASSERT(!object->paging_in_progress,
("vm_object_terminate: pageout in progress"));
* Wait for any I/O to complete, after which there had better not
* be any references left on the object.
*/
- vm_object_pip_wait(object, "objtrm");
+ vm_object_pip_wait(object, "objtrm2");
if (object->ref_count != 0) {
panic("vm_object_terminate: object with references, "
lwkt_reltoken(&vm_token);
/*
+ * Wait for the object hold count to hit zero
+ */
+ vm_object_hold_wait(object);
+
+ /*
* Let the pager know object is dead.
*/
vm_pager_deallocate(object);
"over pages during collapse!",
backing_object));
+ /*
+ * Wait for hold count to hit zero
+ */
+ vm_object_hold_wait(backing_object);
+
/* (we are holding vmobj_token) */
TAILQ_REMOVE(&vm_object_list, backing_object,
object_list);
return (TRUE);
}
- vm_object_lock(prev_object);
if (prev_object->type != OBJT_DEFAULT &&
prev_object->type != OBJT_SWAP) {
- vm_object_unlock(prev_object);
return (FALSE);
}
*/
if (prev_object->backing_object != NULL) {
- vm_object_unlock(prev_object);
return (FALSE);
}
if ((prev_object->ref_count > 1) &&
(prev_object->size != next_pindex)) {
- vm_object_unlock(prev_object);
return (FALSE);
}
if (next_pindex + next_size > prev_object->size)
prev_object->size = next_pindex + next_size;
- vm_object_unlock(prev_object);
return (TRUE);
}
lwkt_reltoken(&vm_token);
}
+static void
+vm_object_lock_init(vm_object_t obj)
+{
+}
+
+void
+vm_object_lock(vm_object_t obj)
+{
+ lwkt_getpooltoken(obj);
+}
+
void
-vm_object_lock(vm_object_t object)
+vm_object_unlock(vm_object_t obj)
{
- lwkt_gettoken(&object->tok);
+ lwkt_relpooltoken(obj);
}
void
-vm_object_unlock(vm_object_t object)
+vm_object_hold(vm_object_t obj)
{
- lwkt_reltoken(&object->tok);
+ vm_object_lock(obj);
+
+ refcount_acquire(&obj->hold_count);
+}
+
+void
+vm_object_drop(vm_object_t obj)
+{
+ int rc;
+
+ rc = refcount_release(&obj->hold_count);
+ vm_object_unlock(obj);
+
+ if (rc)
+ vm_object_hold_wake(obj);
+}
+
+static void
+vm_object_hold_wake(vm_object_t obj)
+{
+ wakeup(obj);
+}
+
+static void
+vm_object_hold_wait(vm_object_t obj)
+{
+ vm_object_lock(obj);
+
+ while (obj->hold_count)
+ tsleep(obj, 0, "vmobjhld", 0);
+
+ vm_object_unlock(obj);
}
#include "opt_ddb.h"
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
vm_pindex_t size; /* Object size */
int ref_count; /* vmobj_token */
int shadow_count; /* how many objects that this is a shadow for */
- int hash_rand; /* vm hash table randomizer */
objtype_t type; /* type of pager */
u_short flags; /* see below */
u_short pg_color; /* color of first page in obj */
- u_short unused01;
int paging_in_progress; /* Paging (in or out) so don't collapse or destroy */
int resident_page_count; /* number of resident pages */
u_int agg_pv_list_count; /* aggregate pv list count */
struct vm_object *backing_object; /* object that I'm a shadow of */
vm_ooffset_t backing_object_offset;/* Offset in backing object */
- TAILQ_ENTRY(vm_object) pager_object_list; /* list of all objects of this pager type */
void *handle;
- struct lwkt_token tok;
+ int hold_count; /* refcount for object liveness */
union {
/*
}
static __inline void
-vm_object_pip_wakeup(vm_object_t object)
+vm_object_pip_wakeupn(vm_object_t object, int i)
{
- atomic_subtract_int(&object->paging_in_progress, 1);
+ if (i)
+ atomic_subtract_int(&object->paging_in_progress, i);
if ((object->flags & OBJ_PIPWNT) && object->paging_in_progress == 0) {
vm_object_clear_flag(object, OBJ_PIPWNT);
wakeup(object);
}
static __inline void
-vm_object_pip_wakeupn(vm_object_t object, int i)
+vm_object_pip_wakeup(vm_object_t object)
{
- if (i)
- atomic_subtract_int(&object->paging_in_progress, i);
- if ((object->flags & OBJ_PIPWNT) && object->paging_in_progress == 0) {
- vm_object_clear_flag(object, OBJ_PIPWNT);
- wakeup(object);
- }
+ vm_object_pip_wakeupn(object, 1);
}
static __inline void
void vm_object_dead_wakeup(vm_object_t);
void vm_object_lock(vm_object_t);
void vm_object_unlock(vm_object_t);
+void vm_object_hold(vm_object_t);
+void vm_object_drop(vm_object_t);
#endif /* _KERNEL */