diff options
author | jhb <jhb@FreeBSD.org> | 2016-01-19 21:37:51 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2016-01-19 21:37:51 +0000 |
commit | 897a9bc5d3677b3f9053d7e36e77e8dc0aa373e0 (patch) | |
tree | 487bad23399744527b32d7512d35abaf220f0d77 /sys/vm/vm_map.c | |
parent | ea0e31cb8f599c0dda524d10f320561820408aac (diff) | |
download | FreeBSD-src-897a9bc5d3677b3f9053d7e36e77e8dc0aa373e0.zip FreeBSD-src-897a9bc5d3677b3f9053d7e36e77e8dc0aa373e0.tar.gz |
Various cleanups to the main function for AIO kernel processes:
- Pull the vmspace logic out into helper functions and reduce duplication.
Operations on the vmspace are all isolated to vm_map.c, but it now exports
a new 'vmspace_switch_aio' for use by AIO kernel processes.
- When an AIO kernel process wants to exit, break out of the main loop and
perform cleanup after the loop end. This reduces a lot of indentation and
allows cleanup to more closely mirror setup actions before the loop starts.
- Convert a DIAGNOSTIC to KASSERT().
- Replace mycp with more typical 'p'.
Reviewed by: kib
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D4990
Diffstat (limited to 'sys/vm/vm_map.c')
-rw-r--r-- | sys/vm/vm_map.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index 2e69b87..5fdc62f 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -451,6 +451,51 @@ vmspace_acquire_ref(struct proc *p) return (vm); } +/* + * Switch between vmspaces in an AIO kernel process. + * + * The AIO kernel processes switch to and from a user process's + * vmspace while performing an I/O operation on behalf of a user + * process. The new vmspace is either the vmspace of a user process + * obtained from an active AIO request or the initial vmspace of the + * AIO kernel process (when it is idling). Because user processes + * will block to drain any active AIO requests before proceeding in + * exit() or execve(), the vmspace reference count for these vmspaces + * can never be 0. This allows for a much simpler implementation than + * the loop in vmspace_acquire_ref() above. Similarly, AIO kernel + * processes hold an extra reference on their initial vmspace for the + * life of the process so that this guarantee is true for any vmspace + * passed as 'newvm'. + */ +void +vmspace_switch_aio(struct vmspace *newvm) +{ + struct vmspace *oldvm; + + /* XXX: Need some way to assert that this is an aio daemon. */ + + KASSERT(newvm->vm_refcnt > 0, + ("vmspace_switch_aio: newvm unreferenced")); + + oldvm = curproc->p_vmspace; + if (oldvm == newvm) + return; + + /* + * Point to the new address space and refer to it. + */ + curproc->p_vmspace = newvm; + atomic_add_int(&newvm->vm_refcnt, 1); + + /* Activate the new mapping. */ + pmap_activate(curthread); + + /* Remove the daemon's reference to the old address space. */ + KASSERT(oldvm->vm_refcnt > 1, + ("vmspace_switch_aio: oldvm dropping last reference")); + vmspace_free(oldvm); +} + void _vm_map_lock(vm_map_t map, const char *file, int line) { |