From: Venkatesh Srinivas Date: Sun, 27 Mar 2011 14:20:20 +0000 (-0700) Subject: kernel -- vm_object locking: DEBUG_LOCKS check for hold_wait vs hold deadlock X-Git-Tag: v2.10.0~137 X-Git-Url: http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/cb443cbb47dab690574674c82ee9407c28deb544 kernel -- vm_object locking: DEBUG_LOCKS check for hold_wait vs hold deadlock If a thread has a hold on a vm_object and enters hold_wait (via either vm_object_terminate or vm_object_collapse), it will wait forever for the hold count to hit 0. Record the threads holding an object in a per-object array. --- diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 499a0a4..e227ccd 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -1819,6 +1819,14 @@ vm_object_set_writeable_dirty(vm_object_t object) static void vm_object_lock_init(vm_object_t obj) { +#if defined(DEBUG_LOCKS) + int i; + + obj->debug_hold_bitmap = 0; + for (i = 0; i < VMOBJ_DEBUG_ARRAY_SIZE; i++) { + obj->debug_hold_thrs[i] = NULL; + } +#endif } void @@ -1839,6 +1847,18 @@ vm_object_hold(vm_object_t obj) vm_object_lock(obj); refcount_acquire(&obj->hold_count); + +#if defined(DEBUG_LOCKS) + int i; + + i = ffs(~obj->debug_hold_bitmap) - 1; + if (i == -1) { + panic("vm_object hold count > VMOBJ_DEBUG_ARRAY_SIZE"); + } + + obj->debug_hold_bitmap |= (1 << i); + obj->debug_hold_thrs[i] = curthread; +#endif } void @@ -1846,6 +1866,24 @@ vm_object_drop(vm_object_t obj) { int rc; +#if defined(DEBUG_LOCKS) + int found = 0; + int i; + + for (i = 0; i < VMOBJ_DEBUG_ARRAY_SIZE; i++) { + if ((obj->debug_hold_bitmap & (1 << i)) && + (obj->debug_hold_thrs[i] == curthread)) { + obj->debug_hold_bitmap &= ~(1 << i); + obj->debug_hold_thrs[i] = NULL; + found = 1; + break; + } + } + + if (found == 0) + panic("vm_object: attempt to drop hold on non-self-held obj"); +#endif + rc = refcount_release(&obj->hold_count); vm_object_unlock(obj); @@ -1864,6 +1902,16 @@ vm_object_hold_wait(vm_object_t obj) { vm_object_lock(obj); +#if defined(DEBUG_LOCKS) + int i; + + for (i = 0; i < VMOBJ_DEBUG_ARRAY_SIZE; i++) { + if ((obj->debug_hold_bitmap & (1 << i)) && + (obj->debug_hold_thrs[i] == curthread)) + panic("vm_object: self-hold in terminate or collapse"); + } +#endif + while (obj->hold_count) tsleep(obj, 0, "vmobjhld", 0); diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h index cb29529..68769f2 100644 --- a/sys/vm/vm_object.h +++ b/sys/vm/vm_object.h @@ -147,6 +147,17 @@ struct vm_object { void *handle; int hold_count; /* refcount for object liveness */ +#if defined(DEBUG_LOCKS) + /* + * Record threads holding a vm_object + */ + +#define VMOBJ_DEBUG_ARRAY_SIZE (32) + u_int debug_hold_bitmap; + thread_t debug_hold_thrs[VMOBJ_DEBUG_ARRAY_SIZE]; + +#endif + union { /* * Device pager