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;
}