Author: kib
Date: Sun Feb  8 20:39:17 2009
New Revision: 188334
URL: http://svn.freebsd.org/changeset/base/188334

Log:
  Do not call vm_object_deallocate() from vm_map_delete(), because we
  hold the map lock there, and might need the vnode lock for OBJT_VNODE
  objects. Postpone object deallocation until caller of vm_map_delete()
  drops the map lock. Link the map entries to be freed into the freelist,
  that is released by the new helper function vm_map_entry_free_freelist().
  
  Reviewed by:  tegge, alc
  Tested by:    pho

Modified:
  head/sys/vm/vm_kern.c
  head/sys/vm/vm_map.c
  head/sys/vm/vm_map.h
  head/sys/vm/vm_mmap.c
  head/sys/vm/vm_unix.c

Modified: head/sys/vm/vm_kern.c
==============================================================================
--- head/sys/vm/vm_kern.c       Sun Feb  8 20:30:51 2009        (r188333)
+++ head/sys/vm/vm_kern.c       Sun Feb  8 20:39:17 2009        (r188334)
@@ -271,7 +271,7 @@ kmem_malloc(map, size, flags)
        int flags;
 {
        vm_offset_t offset, i;
-       vm_map_entry_t entry;
+       vm_map_entry_t entry, freelist;
        vm_offset_t addr;
        vm_page_t m;
        int pflags;
@@ -355,8 +355,10 @@ retry:
                                vm_page_unlock_queues();
                        }
                        VM_OBJECT_UNLOCK(kmem_object);
-                       vm_map_delete(map, addr, addr + size);
+                       freelist = NULL;
+                       vm_map_delete(map, addr, addr + size, &freelist);
                        vm_map_unlock(map);
+                       vm_map_entry_free_freelist(map, freelist);
                        return (0);
                }
                if (flags & M_ZERO && (m->flags & PG_ZERO) == 0)
@@ -455,14 +457,18 @@ kmem_free_wakeup(map, addr, size)
        vm_offset_t addr;
        vm_size_t size;
 {
+       vm_map_entry_t freelist;
 
+       freelist = NULL;
        vm_map_lock(map);
-       (void) vm_map_delete(map, trunc_page(addr), round_page(addr + size));
+       (void) vm_map_delete(map, trunc_page(addr), round_page(addr + size),
+            &freelist);
        if (map->needs_wakeup) {
                map->needs_wakeup = FALSE;
                vm_map_wakeup(map);
        }
        vm_map_unlock(map);
+       vm_map_entry_free_freelist(map, freelist);
 }
 
 /*

Modified: head/sys/vm/vm_map.c
==============================================================================
--- head/sys/vm/vm_map.c        Sun Feb  8 20:30:51 2009        (r188333)
+++ head/sys/vm/vm_map.c        Sun Feb  8 20:39:17 2009        (r188334)
@@ -1261,16 +1261,19 @@ vm_map_fixed(vm_map_t map, vm_object_t o
     vm_offset_t start, vm_size_t length, vm_prot_t prot,
     vm_prot_t max, int cow)
 {
+       vm_map_entry_t freelist;
        vm_offset_t end;
        int result;
 
-       vm_map_lock(map);
        end = start + length;
+       freelist = NULL;
+       vm_map_lock(map);
        VM_MAP_RANGE_CHECK(map, start, end);
-       (void) vm_map_delete(map, start, end);
+       (void) vm_map_delete(map, start, end, &freelist);
        result = vm_map_insert(map, object, offset, start, end, prot,
            max, cow);
        vm_map_unlock(map);
+       vm_map_entry_free_freelist(map, freelist);
        return (result);
 }
 
@@ -2392,6 +2395,23 @@ vm_map_entry_unwire(vm_map_t map, vm_map
        entry->wired_count = 0;
 }
 
+void
+vm_map_entry_free_freelist(vm_map_t map, vm_map_entry_t freelist)
+{
+       vm_map_entry_t e;
+       vm_object_t object;
+
+       while (freelist != NULL) {
+               e = freelist;
+               freelist = freelist->next;
+               if ((e->eflags & MAP_ENTRY_IS_SUB_MAP) == 0) {
+                       object = e->object.vm_object;
+                       vm_object_deallocate(object);
+               }
+               vm_map_entry_dispose(map, e);
+       }
+}
+
 /*
  *     vm_map_entry_delete:    [ internal use only ]
  *
@@ -2424,10 +2444,8 @@ vm_map_entry_delete(vm_map_t map, vm_map
                                object->size = offidxstart;
                }
                VM_OBJECT_UNLOCK(object);
-               vm_object_deallocate(object);
-       }
-
-       vm_map_entry_dispose(map, entry);
+       } else
+               entry->object.vm_object = NULL;
 }
 
 /*
@@ -2437,7 +2455,8 @@ vm_map_entry_delete(vm_map_t map, vm_map
  *     map.
  */
 int
-vm_map_delete(vm_map_t map, vm_offset_t start, vm_offset_t end)
+vm_map_delete(vm_map_t map, vm_offset_t start, vm_offset_t end,
+    vm_map_entry_t *freelist)
 {
        vm_map_entry_t entry;
        vm_map_entry_t first_entry;
@@ -2514,6 +2533,8 @@ vm_map_delete(vm_map_t map, vm_offset_t 
                 * modify bits will be set in the wrong object!)
                 */
                vm_map_entry_delete(map, entry);
+               entry->next = *freelist;
+               *freelist = entry;
                entry = next;
        }
        return (KERN_SUCCESS);
@@ -2528,12 +2549,15 @@ vm_map_delete(vm_map_t map, vm_offset_t 
 int
 vm_map_remove(vm_map_t map, vm_offset_t start, vm_offset_t end)
 {
+       vm_map_entry_t freelist;
        int result;
 
+       freelist = NULL;
        vm_map_lock(map);
        VM_MAP_RANGE_CHECK(map, start, end);
-       result = vm_map_delete(map, start, end);
+       result = vm_map_delete(map, start, end, &freelist);
        vm_map_unlock(map);
+       vm_map_entry_free_freelist(map, freelist);
        return (result);
 }
 

Modified: head/sys/vm/vm_map.h
==============================================================================
--- head/sys/vm/vm_map.h        Sun Feb  8 20:30:51 2009        (r188333)
+++ head/sys/vm/vm_map.h        Sun Feb  8 20:39:17 2009        (r188334)
@@ -157,6 +157,8 @@ vm_map_entry_system_wired_count(vm_map_e
 {
        return (entry->wired_count - vm_map_entry_user_wired_count(entry));
 }
+
+void vm_map_entry_free_freelist(vm_map_t map, vm_map_entry_t freelist);
 #endif /* _KERNEL */
 
 /*
@@ -336,7 +338,7 @@ long vmspace_wired_count(struct vmspace 
 #ifdef _KERNEL
 boolean_t vm_map_check_protection (vm_map_t, vm_offset_t, vm_offset_t, 
vm_prot_t);
 vm_map_t vm_map_create(pmap_t, vm_offset_t, vm_offset_t);
-int vm_map_delete (vm_map_t, vm_offset_t, vm_offset_t);
+int vm_map_delete(vm_map_t, vm_offset_t, vm_offset_t, vm_map_entry_t *);
 int vm_map_find(vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t *, vm_size_t,
     int, vm_prot_t, vm_prot_t, int);
 int vm_map_fixed(vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t, vm_size_t,

Modified: head/sys/vm/vm_mmap.c
==============================================================================
--- head/sys/vm/vm_mmap.c       Sun Feb  8 20:30:51 2009        (r188333)
+++ head/sys/vm/vm_mmap.c       Sun Feb  8 20:39:17 2009        (r188334)
@@ -552,6 +552,7 @@ munmap(td, uap)
        vm_offset_t addr;
        vm_size_t size, pageoff;
        vm_map_t map;
+       vm_map_entry_t freelist;
 
        addr = (vm_offset_t) uap->addr;
        size = uap->len;
@@ -571,6 +572,7 @@ munmap(td, uap)
        map = &td->td_proc->p_vmspace->vm_map;
        if (addr < vm_map_min(map) || addr + size > vm_map_max(map))
                return (EINVAL);
+       freelist = NULL;
        vm_map_lock(map);
 #ifdef HWPMC_HOOKS
        /*
@@ -593,8 +595,9 @@ munmap(td, uap)
        }
 #endif
        /* returns nothing but KERN_SUCCESS anyway */
-       vm_map_delete(map, addr, addr + size);
+       vm_map_delete(map, addr, addr + size, &freelist);
        vm_map_unlock(map);
+       vm_map_entry_free_freelist(map, freelist);
        return (0);
 }
 

Modified: head/sys/vm/vm_unix.c
==============================================================================
--- head/sys/vm/vm_unix.c       Sun Feb  8 20:30:51 2009        (r188333)
+++ head/sys/vm/vm_unix.c       Sun Feb  8 20:39:17 2009        (r188334)
@@ -72,6 +72,7 @@ obreak(td, uap)
        struct obreak_args *uap;
 {
        struct vmspace *vm = td->td_proc->p_vmspace;
+       vm_map_entry_t freelist;
        vm_offset_t new, old, base;
        rlim_t datalim, vmemlim;
        int rv;
@@ -85,6 +86,7 @@ obreak(td, uap)
 
        do_map_wirefuture = FALSE;
        new = round_page((vm_offset_t)uap->nsize);
+       freelist = NULL;
        vm_map_lock(&vm->vm_map);
 
        base = round_page((vm_offset_t) vm->vm_daddr);
@@ -138,7 +140,7 @@ obreak(td, uap)
                        do_map_wirefuture = TRUE;
                }
        } else if (new < old) {
-               rv = vm_map_delete(&vm->vm_map, new, old);
+               rv = vm_map_delete(&vm->vm_map, new, old, &freelist);
                if (rv != KERN_SUCCESS) {
                        error = ENOMEM;
                        goto done;
@@ -147,6 +149,7 @@ obreak(td, uap)
        }
 done:
        vm_map_unlock(&vm->vm_map);
+       vm_map_entry_free_freelist(&vm->vm_map, freelist);
 
        if (do_map_wirefuture)
                (void) vm_map_wire(&vm->vm_map, old, new,
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to