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
This commit is contained in:
parent
e53fa61bf2
commit
897d81a020
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=188334
@ -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 @@ kmem_malloc(map, size, flags)
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1261,16 +1261,19 @@ vm_map_fixed(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
|
||||
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_t entry)
|
||||
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_entry_t entry)
|
||||
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_entry_t entry)
|
||||
* 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 start, vm_offset_t end)
|
||||
* 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 start, vm_offset_t end)
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -157,6 +157,8 @@ vm_map_entry_system_wired_count(vm_map_entry_t entry)
|
||||
{
|
||||
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 *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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user