Module Name: src Committed By: rmind Date: Sat Jun 18 21:13:29 UTC 2011
Modified Files: src/sys/uvm: uvm_amap.c Log Message: Clean up, sprinkle asserts, consify, use unsigned, use kmem_zalloc instead of memset, reduce the scope of some variables, improve some comments. No functional change intended. To generate a diff of this commit: cvs rdiff -u -r1.94 -r1.95 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.94 src/sys/uvm/uvm_amap.c:1.95 --- src/sys/uvm/uvm_amap.c:1.94 Sat Jun 18 20:51:22 2011 +++ src/sys/uvm/uvm_amap.c Sat Jun 18 21:13:29 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_amap.c,v 1.94 2011/06/18 20:51:22 rmind Exp $ */ +/* $NetBSD: uvm_amap.c,v 1.95 2011/06/18 21:13:29 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.94 2011/06/18 20:51:22 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_amap.c,v 1.95 2011/06/18 21:13:29 rmind Exp $"); #include "opt_uvmhist.h" @@ -160,24 +160,22 @@ #endif /* UVM_AMAP_PPREF */ /* - * amap_alloc1: internal function that allocates an amap, but does not - * init the overlay. + * amap_alloc1: allocate an amap, but do not initialise the overlay. * - * => lock is not initialized + * => Note: lock is not set. */ static inline struct vm_amap * -amap_alloc1(int slots, int padslots, int waitf) +amap_alloc1(int slots, int padslots, int flags) { + const bool nowait = (flags & UVM_FLAG_NOWAIT) != 0; + const km_flag_t kmflags = nowait ? KM_NOSLEEP : KM_SLEEP; struct vm_amap *amap; int totalslots; - km_flag_t kmflags; - amap = pool_cache_get(&uvm_amap_cache, - ((waitf & UVM_FLAG_NOWAIT) != 0) ? PR_NOWAIT : PR_WAITOK); - if (amap == NULL) - return(NULL); - - kmflags = ((waitf & UVM_FLAG_NOWAIT) != 0) ? KM_NOSLEEP : KM_SLEEP; + amap = pool_cache_get(&uvm_amap_cache, nowait ? PR_NOWAIT : PR_WAITOK); + if (amap == NULL) { + return NULL; + } totalslots = amap_roundup_slots(slots + padslots); amap->am_lock = NULL; amap->am_ref = 1; @@ -206,7 +204,7 @@ if (amap->am_anon == NULL) goto fail3; - return(amap); + return amap; fail3: kmem_free(amap->am_bckptr, totalslots * sizeof(int)); @@ -219,13 +217,13 @@ * XXX hack to tell the pagedaemon how many pages we need, * since we can need more than it would normally free. */ - if ((waitf & UVM_FLAG_NOWAIT) != 0) { + if (nowait) { extern u_int uvm_extrapages; atomic_add_int(&uvm_extrapages, ((sizeof(int) * 2 + sizeof(struct vm_anon *)) * totalslots) >> PAGE_SHIFT); } - return (NULL); + return NULL; } /* @@ -647,7 +645,8 @@ amap_share_protect(struct vm_map_entry *entry, vm_prot_t prot) { struct vm_amap *amap = entry->aref.ar_amap; - int slots, lcv, slot, stop; + u_int slots, lcv, slot, stop; + struct vm_anon *anon; KASSERT(mutex_owned(amap->am_lock)); @@ -655,48 +654,57 @@ stop = entry->aref.ar_pageoff + slots; if (slots < amap->am_nused) { - /* cheaper to traverse am_anon */ + /* + * Cheaper to traverse am_anon. + */ for (lcv = entry->aref.ar_pageoff ; lcv < stop ; lcv++) { - if (amap->am_anon[lcv] == NULL) + anon = amap->am_anon[lcv]; + if (anon == NULL) { continue; - if (amap->am_anon[lcv]->an_page != NULL) - pmap_page_protect(amap->am_anon[lcv]->an_page, - prot); + } + if (anon->an_page) { + pmap_page_protect(anon->an_page, prot); + } } return; } - /* cheaper to traverse am_slots */ + /* + * Cheaper to traverse am_slots. + */ for (lcv = 0 ; lcv < amap->am_nused ; lcv++) { slot = amap->am_slots[lcv]; - if (slot < entry->aref.ar_pageoff || slot >= stop) + if (slot < entry->aref.ar_pageoff || slot >= stop) { continue; - if (amap->am_anon[slot]->an_page != NULL) - pmap_page_protect(amap->am_anon[slot]->an_page, prot); + } + anon = amap->am_anon[slot]; + if (anon->an_page) { + pmap_page_protect(anon->an_page, prot); + } } } /* * amap_wipeout: wipeout all anon's in an amap; then free the amap! * - * => called from amap_unref when the final reference to an amap is - * discarded (i.e. when reference count drops to 0) - * => the amap should be locked (by the caller) + * => Called from amap_unref(), when reference count drops to zero. + * => amap must be locked. */ void amap_wipeout(struct vm_amap *amap) { - int lcv, slot; - struct vm_anon *anon; + u_int lcv; + UVMHIST_FUNC("amap_wipeout"); UVMHIST_CALLED(maphist); UVMHIST_LOG(maphist,"(amap=0x%x)", amap, 0,0,0); + KASSERT(mutex_owned(amap->am_lock)); KASSERT(amap->am_ref == 0); - if (__predict_false((amap->am_flags & AMAP_SWAPOFF) != 0)) { + if (__predict_false(amap->am_flags & AMAP_SWAPOFF)) { /* - * amap_swap_off will call us again. + * Note: amap_swap_off() will call us again. */ amap_unlock(amap); return; @@ -704,7 +712,8 @@ amap_list_remove(amap); for (lcv = 0 ; lcv < amap->am_nused ; lcv++) { - int refs; + struct vm_anon *anon; + u_int slot; slot = amap->am_slots[lcv]; anon = amap->am_anon[slot]; @@ -713,27 +722,26 @@ KASSERT(anon->an_lock == amap->am_lock); UVMHIST_LOG(maphist," processing anon 0x%x, ref=%d", anon, anon->an_ref, 0, 0); - refs = --anon->an_ref; - if (refs == 0) { - /* - * we had the last reference to a vm_anon. free it. - */ + /* + * Drop the reference, and free the anon, if it is last. + */ + if (--anon->an_ref == 0) { uvm_anfree(anon); } - - if (curlwp->l_cpu->ci_schedstate.spc_flags & SPCF_SHOULDYIELD) + if (curlwp->l_cpu->ci_schedstate.spc_flags & SPCF_SHOULDYIELD) { preempt(); + } } /* - * now we free the map + * Finally, destroy the amap. */ amap->am_nused = 0; amap_unlock(amap); - amap_free(amap); /* will unlock and free amap */ + amap_free(amap); UVMHIST_LOG(maphist,"<- done!", 0,0,0,0); } @@ -947,9 +955,9 @@ amap_cow_now(struct vm_map *map, struct vm_map_entry *entry) { struct vm_amap *amap = entry->aref.ar_amap; - int lcv, slot; struct vm_anon *anon, *nanon; struct vm_page *pg, *npg; + u_int lcv, slot; /* * note that if we unlock the amap then we must ReStart the "lcv" for @@ -960,20 +968,15 @@ ReStart: amap_lock(amap); for (lcv = 0 ; lcv < amap->am_nused ; lcv++) { - - /* - * get the page - */ - slot = amap->am_slots[lcv]; anon = amap->am_anon[slot]; KASSERT(anon->an_lock == amap->am_lock); /* - * If the anon has only one ref, we must have already copied it. - * This can happen if we needed to sleep waiting for memory - * in a previous run through this loop. The new page might - * even have been paged out, since the new page is not wired. + * If anon has only one reference - we must have already + * copied it. This can happen if we needed to sleep waiting + * for memory in a previous run through this loop. The new + * page might even have been paged out, since is not wired. */ if (anon->an_ref == 1) { @@ -1000,7 +1003,7 @@ KASSERT(pg->uanon == anon && pg->uobject == NULL); /* - * if the page is busy then we have to unlock, wait for + * If the page is busy, then we have to unlock, wait for * it and then restart. */ @@ -1012,14 +1015,16 @@ } /* - * ok, time to do a copy-on-write to a new anon + * Perform a copy-on-write. + * First - get a new anon and a page. */ nanon = uvm_analloc(); if (nanon) { npg = uvm_pagealloc(NULL, 0, nanon, 0); - } else - npg = NULL; /* XXX: quiet gcc warning */ + } else { + npg = NULL; + } if (nanon == NULL || npg == NULL) { /* @@ -1037,19 +1042,20 @@ } /* - * got it... now we can copy the data and replace anon - * with our new one... + * Copy the data and replace anon with the new one. + * Also, setup its lock (share the with amap's lock). */ nanon->an_lock = amap->am_lock; mutex_obj_hold(nanon->an_lock); - uvm_pagecopy(pg, npg); /* old -> new */ - anon->an_ref--; /* can't drop to zero */ - amap->am_anon[slot] = nanon; /* replace */ + uvm_pagecopy(pg, npg); + anon->an_ref--; + KASSERT(anon->an_ref > 0); + amap->am_anon[slot] = nanon; /* - * drop PG_BUSY on new page ... since we have had its owner - * locked the whole time it can't be PG_RELEASED or PG_WANTED. + * Drop PG_BUSY on new page. Since its owner was locked all + * this time - it cannot be PG_RELEASED or PG_WANTED. */ mutex_enter(&uvm_pageqlock); @@ -1071,85 +1077,75 @@ void amap_splitref(struct vm_aref *origref, struct vm_aref *splitref, vaddr_t offset) { - int leftslots; - struct vm_amap *amap; + struct vm_amap *amap = origref->ar_amap; + u_int leftslots; KASSERT(splitref->ar_amap == origref->ar_amap); AMAP_B2SLOT(leftslots, offset); KASSERT(leftslots != 0); - amap = origref->ar_amap; amap_lock(amap); - - /* - * now: amap is locked and we have a valid am_mapped array. - */ KASSERT(amap->am_nslot - origref->ar_pageoff - leftslots > 0); #ifdef UVM_AMAP_PPREF - /* - * establish ppref before we add a duplicate reference to the amap - */ - if (amap->am_ppref == NULL) + /* Establish ppref before we add a duplicate reference to the amap. */ + if (amap->am_ppref == NULL) { amap_pp_establish(amap, origref->ar_pageoff); + } #endif - - amap->am_ref++; /* not a share reference */ + /* Note: not a share reference. */ + amap->am_ref++; splitref->ar_pageoff = origref->ar_pageoff + leftslots; - amap_unlock(amap); } #ifdef UVM_AMAP_PPREF /* - * amap_pp_establish: add a ppref array to an amap, if possible + * amap_pp_establish: add a ppref array to an amap, if possible. * - * => amap locked by caller + * => amap should be locked by caller. */ void amap_pp_establish(struct vm_amap *amap, vaddr_t offset) { + const size_t sz = amap->am_maxslot * sizeof(*amap->am_ppref); - amap->am_ppref = kmem_alloc(amap->am_maxslot * sizeof(*amap->am_ppref), - KM_NOSLEEP); - - /* - * if we fail then we just won't use ppref for this amap - */ + KASSERT(mutex_owned(amap->am_lock)); + amap->am_ppref = kmem_zalloc(sz, KM_NOSLEEP); if (amap->am_ppref == NULL) { - amap->am_ppref = PPREF_NONE; /* not using it */ + /* Failure - just do not use ppref. */ + amap->am_ppref = PPREF_NONE; return; } - memset(amap->am_ppref, 0, sizeof(int) * amap->am_maxslot); pp_setreflen(amap->am_ppref, 0, 0, offset); pp_setreflen(amap->am_ppref, offset, amap->am_ref, amap->am_nslot - offset); - return; } /* * amap_pp_adjref: adjust reference count to a part of an amap using the * per-page reference count array. * - * => map and amap locked by caller - * => caller must check that ppref != PPREF_NONE before calling + * => caller must check that ppref != PPREF_NONE before calling. + * => map and amap must be locked. */ void amap_pp_adjref(struct vm_amap *amap, int curslot, vsize_t slotlen, int adjval, - struct vm_anon **tofree) + struct vm_anon **tofree) { int stopslot, *ppref, lcv, prevlcv; int ref, len, prevref, prevlen; + KASSERT(mutex_owned(amap->am_lock)); + stopslot = curslot + slotlen; ppref = amap->am_ppref; prevlcv = 0; /* - * first advance to the correct place in the ppref array, - * fragment if needed. + * Advance to the correct place in the array, fragment if needed. */ for (lcv = 0 ; lcv < curslot ; lcv += len) { @@ -1161,20 +1157,20 @@ } prevlcv = lcv; } - if (lcv != 0) - pp_getreflen(ppref, prevlcv, &prevref, &prevlen); - else { - /* Ensure that the "prevref == ref" test below always - * fails, since we're starting from the beginning of - * the ppref array; that is, there is no previous - * chunk. + if (lcv) { + /* + * Ensure that the "prevref == ref" test below always + * fails, since we are starting from the beginning of + * the ppref array; that is, there is no previous chunk. */ prevref = -1; prevlen = 0; + } else { + pp_getreflen(ppref, prevlcv, &prevref, &prevlen); } /* - * now adjust reference counts in range. merge the first + * Now adjust reference counts in range. Merge the first * changed entry with the last unchanged entry if possible. */ KASSERT(lcv == curslot); @@ -1193,10 +1189,10 @@ } else { pp_setreflen(ppref, lcv, ref, len); } - if (ref == 0) + if (ref == 0) { amap_wiperange(amap, lcv, len, tofree); + } } - } /* @@ -1207,10 +1203,11 @@ */ void amap_wiperange(struct vm_amap *amap, int slotoff, int slots, - struct vm_anon **tofree) + struct vm_anon **tofree) { - int byanon, lcv, stop, curslot, ptr, slotend; + u_int lcv, stop, curslot, ptr, slotend; struct vm_anon *anon; + bool byanon; KASSERT(mutex_owned(amap->am_lock)); @@ -1232,8 +1229,6 @@ } while (lcv < stop) { - int refs; - if (byanon) { curslot = lcv++; /* lcv advances here */ if (amap->am_anon[curslot] == NULL) @@ -1249,7 +1244,7 @@ anon = amap->am_anon[curslot]; /* - * remove it from the amap + * Remove anon from the amap. */ amap->am_anon[curslot] = NULL; @@ -1263,19 +1258,15 @@ amap->am_nused--; /* - * drop anon reference count + * Drop its reference count. */ KASSERT(anon->an_lock == amap->am_lock); - refs = --anon->an_ref; - if (refs == 0) { - + if (--anon->an_ref == 0) { /* - * we just eliminated the last reference to an anon. - * defer freeing it as uvm_anfree() can unlock the - * amap. + * Eliminated the last reference to an anon - defer + * freeing as uvm_anfree() can unlock the amap. */ - anon->an_link = *tofree; *tofree = anon; }