}
if (temp->ref_count == 1) {
- temp->ref_count--;
vm_object_unlock(object);
object = temp;
goto doterm;
/*
* Normal dereferencing path
*/
- object->ref_count--;
- if (object->ref_count != 0) {
+ if (object->ref_count >= 2) {
+ object->ref_count--;
lwkt_reltoken(&vm_token);
vm_object_unlock(object);
break;
* temp's lock. If temp is non NULL we have to swap the
* lock order so the original object lock as at the top
* of the lock heap.
+ *
+ * object has 1 ref which we can't reduce until after we have
+ * locked temp.
*/
lwkt_reltoken(&vm_token);
doterm:
break;
vm_object_unlock(temp);
}
+
+ /*
+ * re-check
+ */
+ if (object->ref_count >= 2) {
+ object->ref_count--;
+ if (temp)
+ vm_object_unlock(temp);
+ vm_object_unlock(object);
+ break;
+ }
+ KKASSERT(object->ref_count == 1);
+ object->ref_count = 0;
+
if (temp) {
LIST_REMOVE(object, shadow_list);
temp->shadow_count--;
source = *object;
+ if (source)
+ vm_object_hold(source);
+
/*
* Don't create the new object if the old object isn't shared.
*/
(source->type == OBJT_DEFAULT ||
source->type == OBJT_SWAP)) {
lwkt_reltoken(&vm_token);
+ vm_object_drop(source);
return;
}
result->backing_object_offset = *offset;
lwkt_reltoken(&vm_token);
+ if (source)
+ vm_object_drop(source);
+
/*
* Return the new things
*/