diff options
author | Alfred Perlstein <alfred@FreeBSD.org> | 2001-05-19 01:28:09 +0000 |
---|---|---|
committer | Alfred Perlstein <alfred@FreeBSD.org> | 2001-05-19 01:28:09 +0000 |
commit | 2395531439bb140427dff4dfd6d67856f907c15e (patch) | |
tree | 7d51c8cab74aeec829658414e052238902ea14a0 /sys/vm/vm_fault.c | |
parent | 3620eb66f3ef16ff28810c74476f01e29c1562bf (diff) | |
download | src-test2-2395531439bb140427dff4dfd6d67856f907c15e.tar.gz src-test2-2395531439bb140427dff4dfd6d67856f907c15e.zip |
Notes
Diffstat (limited to 'sys/vm/vm_fault.c')
-rw-r--r-- | sys/vm/vm_fault.c | 65 |
1 files changed, 61 insertions, 4 deletions
diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index a1bad69dadae..f31f12b64774 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -81,6 +81,8 @@ #include <sys/vnode.h> #include <sys/resourcevar.h> #include <sys/vmmeter.h> +#include <sys/kernel.h> +#include <sys/sysctl.h> #include <vm/vm.h> #include <vm/vm_param.h> @@ -134,6 +136,8 @@ unlock_map(struct faultstate *fs) static void _unlock_things(struct faultstate *fs, int dealloc) { + + mtx_assert(&vm_mtx, MA_OWNED); vm_object_pip_wakeup(fs->object); if (fs->object != fs->first_object) { vm_page_free(fs->first_m); @@ -145,8 +149,15 @@ _unlock_things(struct faultstate *fs, int dealloc) } unlock_map(fs); if (fs->vp != NULL) { - vput(fs->vp); + struct vnode *vp; + + vp = fs->vp; fs->vp = NULL; + mtx_unlock(&vm_mtx); + mtx_lock(&Giant); + vput(vp); + mtx_unlock(&Giant); + mtx_lock(&vm_mtx); } } @@ -179,10 +190,41 @@ _unlock_things(struct faultstate *fs, int dealloc) * * * The map in question must be referenced, and remains so. - * Caller may hold no locks. + * Caller may hold no locks except the vm_mtx which will be + * locked if needed. */ +static int vm_fault1 __P((vm_map_t, vm_offset_t, vm_prot_t, int)); + +static int vm_faults_no_vm_mtx; +SYSCTL_INT(_vm, OID_AUTO, vm_faults_no_vm_mtx, CTLFLAG_RW, + &vm_faults_no_vm_mtx, 0, ""); + +static int vm_faults_no_giant; +SYSCTL_INT(_vm, OID_AUTO, vm_faults_no_giant, CTLFLAG_RW, + &vm_faults_no_giant, 0, ""); + int -vm_fault(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type, int fault_flags) +vm_fault(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type, + int fault_flags) +{ + int hadvmlock, ret; + + hadvmlock = mtx_owned(&vm_mtx); + if (!hadvmlock) { + mtx_lock(&vm_mtx); + vm_faults_no_vm_mtx++; + if (!mtx_owned(&Giant)) + vm_faults_no_giant++; + } + ret = vm_fault1(map, vaddr, fault_type, fault_flags); + if (!hadvmlock) + mtx_unlock(&vm_mtx); + return (ret); +} + +static int +vm_fault1(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type, + int fault_flags) { vm_prot_t prot; int result; @@ -194,7 +236,8 @@ vm_fault(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type, int fault_flags) int faultcount; struct faultstate fs; - cnt.v_vm_faults++; /* needs lock XXX */ + mtx_assert(&vm_mtx, MA_OWNED); + cnt.v_vm_faults++; hardfault = 0; RetryFault:; @@ -251,7 +294,11 @@ RetryFault:; vm_object_reference(fs.first_object); vm_object_pip_add(fs.first_object, 1); + mtx_unlock(&vm_mtx); + mtx_lock(&Giant); fs.vp = vnode_pager_lock(fs.first_object); + mtx_unlock(&Giant); + mtx_lock(&vm_mtx); if ((fault_type & VM_PROT_WRITE) && (fs.first_object->type == OBJT_VNODE)) { vm_freeze_copyopts(fs.first_object, @@ -723,7 +770,11 @@ readrest: */ if (fs.vp != NULL) { + mtx_unlock(&vm_mtx); + mtx_lock(&Giant); vput(fs.vp); + mtx_unlock(&Giant); + mtx_lock(&vm_mtx); fs.vp = NULL; } @@ -940,6 +991,7 @@ vm_fault_user_wire(map, start, end) register pmap_t pmap; int rv; + mtx_assert(&vm_mtx, MA_OWNED); pmap = vm_map_pmap(map); /* @@ -1112,6 +1164,9 @@ vm_fault_copy_entry(dst_map, src_map, dst_entry, src_entry) * * Return value: * number of pages in marray + * + * This routine can't block. + * vm_mtx must be held. */ static int vm_fault_additional_pages(m, rbehind, rahead, marray, reqpage) @@ -1127,6 +1182,8 @@ vm_fault_additional_pages(m, rbehind, rahead, marray, reqpage) vm_page_t rtm; int cbehind, cahead; + mtx_assert(&vm_mtx, MA_OWNED); + object = m->object; pindex = m->pindex; |