kernel - Fix vm_object token deadlock (2)
authorMatthew Dillon <dillon@apollo.backplane.com>
Sun, 20 Nov 2011 18:17:12 +0000 (10:17 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Sun, 20 Nov 2011 18:17:12 +0000 (10:17 -0800)
* Files missed in original commit.

sys/vm/vm_object.c
sys/vm/vm_object.h

index a252ec5..93a46f3 100644 (file)
@@ -175,6 +175,15 @@ vm_object_lock(vm_object_t obj)
        lwkt_gettoken(&obj->token);
 }
 
+/*
+ * Returns TRUE on sucesss
+ */
+static int
+vm_object_lock_try(vm_object_t obj)
+{
+       return(lwkt_trytoken(&obj->token));
+}
+
 void
 vm_object_lock_shared(vm_object_t obj)
 {
@@ -236,6 +245,56 @@ debugvm_object_hold(vm_object_t obj, char *file, int line)
 #endif
 }
 
+int
+#ifndef DEBUG_LOCKS
+vm_object_hold_try(vm_object_t obj)
+#else
+debugvm_object_hold_try(vm_object_t obj, char *file, int line)
+#endif
+{
+       KKASSERT(obj != NULL);
+
+       /*
+        * Object must be held (object allocation is stable due to callers
+        * context, typically already holding the token on a parent object)
+        * prior to potentially blocking on the lock, otherwise the object
+        * can get ripped away from us.
+        */
+       refcount_acquire(&obj->hold_count);
+       if (vm_object_lock_try(obj) == 0) {
+               if (refcount_release(&obj->hold_count)) {
+                       if (obj->ref_count == 0 && (obj->flags & OBJ_DEAD))
+                               zfree(obj_zone, obj);
+               }
+               return(0);
+       }
+
+#if defined(DEBUG_LOCKS)
+       int i;
+       u_int mask;
+
+       for (;;) {
+               mask = ~obj->debug_hold_bitmap;
+               cpu_ccfence();
+               if (mask == 0xFFFFFFFFU) {
+                       if (obj->debug_hold_ovfl == 0)
+                               obj->debug_hold_ovfl = 1;
+                       break;
+               }
+               i = ffs(mask) - 1;
+               if (atomic_cmpset_int(&obj->debug_hold_bitmap, ~mask,
+                                     ~mask | (1 << i))) {
+                       obj->debug_hold_bitmap |= (1 << i);
+                       obj->debug_hold_thrs[i] = curthread;
+                       obj->debug_hold_file[i] = file;
+                       obj->debug_hold_line[i] = line;
+                       break;
+               }
+       }
+#endif
+       return(1);
+}
+
 void
 #ifndef DEBUG_LOCKS
 vm_object_hold_shared(vm_object_t obj)
index 82295bb..63e9f9e 100644 (file)
@@ -309,11 +309,15 @@ void vm_object_unlock(vm_object_t);
 
 #ifndef DEBUG_LOCKS
 void vm_object_hold(vm_object_t);
+int vm_object_hold_try(vm_object_t);
 void vm_object_hold_shared(vm_object_t);
 #else
 #define vm_object_hold(obj)            \
        debugvm_object_hold(obj, __FILE__, __LINE__)
 void debugvm_object_hold(vm_object_t, char *, int);
+#define vm_object_hold_try(obj)                \
+       debugvm_object_hold_try(obj, __FILE__, __LINE__)
+int debugvm_object_hold_try(vm_object_t, char *, int);
 #define vm_object_hold_shared(obj)     \
        debugvm_object_hold_shared(obj, __FILE__, __LINE__)
 void debugvm_object_hold_shared(vm_object_t, char *, int);