Module Name: src Committed By: rmind Date: Sat Jun 18 20:29:56 UTC 2011
Modified Files: src/sys/uvm: uvm_amap.c Log Message: Add amap_adjref_anons() helper and simplify amap_ref()/amap_unref(). To generate a diff of this commit: cvs rdiff -u -r1.92 -r1.93 src/sys/uvm/uvm_amap.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/uvm/uvm_amap.c diff -u src/sys/uvm/uvm_amap.c:1.92 src/sys/uvm/uvm_amap.c:1.93 --- src/sys/uvm/uvm_amap.c:1.92 Thu Jun 16 19:42:20 2011 +++ src/sys/uvm/uvm_amap.c Sat Jun 18 20:29:56 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_amap.c,v 1.92 2011/06/16 19:42:20 rmind Exp $ */ +/* $NetBSD: uvm_amap.c,v 1.93 2011/06/18 20:29:56 rmind Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uvm_amap.c,v 1.92 2011/06/16 19:42:20 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_amap.c,v 1.93 2011/06/18 20:29:56 rmind Exp $"); #include "opt_uvmhist.h" @@ -1525,96 +1525,89 @@ } /* - * amap_ref: gain a reference to an amap + * amap_adjref_anons: adjust the reference count(s) on anons of the amap. + */ +static void +amap_adjref_anons(struct vm_amap *amap, vaddr_t offset, vsize_t len, + int refv, bool all) +{ +#ifdef UVM_AMAP_PPREF + KASSERT(mutex_owned(amap->am_lock)); + + if (amap->am_ppref == NULL && !all && len != amap->am_nslot) { + amap_pp_establish(amap, offset); + } + if (amap->am_ppref && amap->am_ppref != PPREF_NONE) { + struct vm_anon *tofree = NULL; + + if (all) { + amap_pp_adjref(amap, 0, amap->am_nslot, refv, &tofree); + } else { + amap_pp_adjref(amap, offset, len, refv, &tofree); + } + uvm_anfree(tofree); + } +#endif +} + +/* + * amap_ref: gain a reference to an amap. * - * => amap must not be locked (we will lock) - * => "offset" and "len" are in units of pages - * => called at fork time to gain the child's reference + * => amap must not be locked (we will lock). + * => "offset" and "len" are in units of pages. + * => Called at fork time to gain the child's reference. */ void amap_ref(struct vm_amap *amap, vaddr_t offset, vsize_t len, int flags) { - UVMHIST_FUNC("amap_ref"); UVMHIST_CALLED(maphist); amap_lock(amap); - if (flags & AMAP_SHARED) + if (flags & AMAP_SHARED) { amap->am_flags |= AMAP_SHARED; -#ifdef UVM_AMAP_PPREF - if (amap->am_ppref == NULL && (flags & AMAP_REFALL) == 0 && - len != amap->am_nslot) - amap_pp_establish(amap, offset); -#endif - amap->am_ref++; -#ifdef UVM_AMAP_PPREF - if (amap->am_ppref && amap->am_ppref != PPREF_NONE) { - struct vm_anon *tofree = NULL; - if (flags & AMAP_REFALL) - amap_pp_adjref(amap, 0, amap->am_nslot, 1, &tofree); - else - amap_pp_adjref(amap, offset, len, 1, &tofree); - uvm_anfree(tofree); /* must be last action before unlock */ } -#endif + amap->am_ref++; + amap_adjref_anons(amap, offset, len, 1, (flags & AMAP_REFALL) != 0); amap_unlock(amap); + UVMHIST_LOG(maphist,"<- done! amap=0x%x", amap, 0, 0, 0); } /* - * amap_unref: remove a reference to an amap + * amap_unref: remove a reference to an amap. * - * => caller must remove all pmap-level references to this amap before - * dropping the reference - * => called from uvm_unmap_detach [only] ... note that entry is no - * longer part of a map - * => amap must be unlocked (we will lock it). + * => All pmap-level references to this amap must be already removed. + * => Called from uvm_unmap_detach(); entry is already removed from the map. + * => We will lock amap, so it must be unlocked. */ void amap_unref(struct vm_amap *amap, vaddr_t offset, vsize_t len, bool all) { - struct vm_anon *tofree; - UVMHIST_FUNC("amap_unref"); UVMHIST_CALLED(maphist); - /* - * lock it - */ amap_lock(amap); + UVMHIST_LOG(maphist," amap=0x%x refs=%d, nused=%d", amap, amap->am_ref, amap->am_nused, 0); + KASSERT(amap->am_ref > 0); - KASSERT(amap_refs(amap) > 0); - - /* - * if we are the last reference, free the amap and return. - */ - - amap->am_ref--; - - if (amap_refs(amap) == 0) { - amap_wipeout(amap); /* drops final ref and frees */ + if (--amap->am_ref == 0) { + /* + * If the last reference - wipeout and destroy the amap. + */ + amap_wipeout(amap); UVMHIST_LOG(maphist,"<- done (was last ref)!", 0, 0, 0, 0); - return; /* no need to unlock */ + return; } /* - * otherwise just drop the reference count(s) + * Otherwise, drop the reference count(s) on anons. */ - if (amap_refs(amap) == 1 && (amap->am_flags & AMAP_SHARED) != 0) - amap->am_flags &= ~AMAP_SHARED; /* clear shared flag */ - tofree = NULL; -#ifdef UVM_AMAP_PPREF - if (amap->am_ppref == NULL && all == 0 && len != amap->am_nslot) - amap_pp_establish(amap, offset); - if (amap->am_ppref && amap->am_ppref != PPREF_NONE) { - if (all) - amap_pp_adjref(amap, 0, amap->am_nslot, -1, &tofree); - else - amap_pp_adjref(amap, offset, len, -1, &tofree); + if (amap->am_ref == 1 && (amap->am_flags & AMAP_SHARED) != 0) { + amap->am_flags &= ~AMAP_SHARED; } -#endif - uvm_anfree(tofree); + amap_adjref_anons(amap, offset, len, -1, all); amap_unlock(amap); UVMHIST_LOG(maphist,"<- done!", 0, 0, 0, 0);