Module Name: src Committed By: rmind Date: Thu Jun 23 18:15:30 UTC 2011
Modified Files: src/sys/uvm: uvm_amap.c Log Message: Clean-up, add asserts, slightly simplify. To generate a diff of this commit: cvs rdiff -u -r1.95 -r1.96 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.95 src/sys/uvm/uvm_amap.c:1.96 --- src/sys/uvm/uvm_amap.c:1.95 Sat Jun 18 21:13:29 2011 +++ src/sys/uvm/uvm_amap.c Thu Jun 23 18:15:30 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_amap.c,v 1.95 2011/06/18 21:13:29 rmind Exp $ */ +/* $NetBSD: uvm_amap.c,v 1.96 2011/06/23 18:15:30 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.95 2011/06/18 21:13:29 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_amap.c,v 1.96 2011/06/23 18:15:30 rmind Exp $"); #include "opt_uvmhist.h" @@ -164,7 +164,7 @@ * * => Note: lock is not set. */ -static inline struct vm_amap * +static struct vm_amap * amap_alloc1(int slots, int padslots, int flags) { const bool nowait = (flags & UVM_FLAG_NOWAIT) != 0; @@ -763,34 +763,39 @@ amap_copy(struct vm_map *map, struct vm_map_entry *entry, int flags, vaddr_t startva, vaddr_t endva) { + const int waitf = (flags & AMAP_COPY_NOWAIT) ? UVM_FLAG_NOWAIT : 0; struct vm_amap *amap, *srcamap; struct vm_anon *tofree; - int slots, lcv; - vaddr_t chunksize; - const int waitf = (flags & AMAP_COPY_NOWAIT) ? UVM_FLAG_NOWAIT : 0; - const bool canchunk = (flags & AMAP_COPY_NOCHUNK) == 0; kmutex_t *lock; + u_int slots, lcv; + vsize_t len; + UVMHIST_FUNC("amap_copy"); UVMHIST_CALLED(maphist); UVMHIST_LOG(maphist, " (map=%p, entry=%p, flags=%d)", map, entry, flags, 0); KASSERT(map != kernel_map); /* we use nointr pool */ + srcamap = entry->aref.ar_amap; + len = entry->end - entry->start; + /* - * is there a map to copy? if not, create one from scratch. + * Is there an amap to copy? If not, create one. */ - if (entry->aref.ar_amap == NULL) { + if (srcamap == NULL) { + const bool canchunk = (flags & AMAP_COPY_NOCHUNK) == 0; /* - * check to see if we have a large amap that we can - * chunk. we align startva/endva to chunk-sized + * Check to see if we have a large amap that we can + * chunk. We align startva/endva to chunk-sized * boundaries and then clip to them. */ - if (canchunk && atop(entry->end - entry->start) >= - UVM_AMAP_LARGE) { - /* convert slots to bytes */ + if (canchunk && atop(len) >= UVM_AMAP_LARGE) { + vsize_t chunksize; + + /* Convert slots to bytes. */ chunksize = UVM_AMAP_CHUNK << PAGE_SHIFT; startva = (startva / chunksize) * chunksize; endva = roundup(endva, chunksize); @@ -798,9 +803,11 @@ "to 0x%x->0x%x", entry->start, entry->end, startva, endva); UVM_MAP_CLIP_START(map, entry, startva, NULL); - /* watch out for endva wrap-around! */ - if (endva >= startva) + + /* Watch out for endva wrap-around! */ + if (endva >= startva) { UVM_MAP_CLIP_END(map, entry, endva, NULL); + } } if ((flags & AMAP_COPY_NOMERGE) == 0 && @@ -809,65 +816,66 @@ } UVMHIST_LOG(maphist, "<- done [creating new amap 0x%x->0x%x]", - entry->start, entry->end, 0, 0); + entry->start, entry->end, 0, 0); + + /* Allocate an initialised amap and install it. */ entry->aref.ar_pageoff = 0; - entry->aref.ar_amap = amap_alloc(entry->end - entry->start, 0, - waitf); - if (entry->aref.ar_amap != NULL) + entry->aref.ar_amap = amap_alloc(len, 0, waitf); + if (entry->aref.ar_amap != NULL) { entry->etype &= ~UVM_ET_NEEDSCOPY; + } return; } /* - * first check and see if we are the only map entry - * referencing the amap we currently have. if so, then we can - * just take it over rather than copying it. note that we are - * reading am_ref with the amap unlocked... the value can only - * be one if we have the only reference to the amap (via our - * locked map). if we are greater than one we fall through to - * the next case (where we double check the value). + * First check and see if we are the only map entry referencing + * he amap we currently have. If so, then just take it over instead + * of copying it. Note that we are reading am_ref without lock held + * as the value value can only be one if we have the only reference + * to the amap (via our locked map). If the value is greater than + * one, then allocate amap and re-check the value. */ - if (entry->aref.ar_amap->am_ref == 1) { + if (srcamap->am_ref == 1) { entry->etype &= ~UVM_ET_NEEDSCOPY; UVMHIST_LOG(maphist, "<- done [ref cnt = 1, took it over]", 0, 0, 0, 0); return; } + UVMHIST_LOG(maphist," amap=%p, ref=%d, must copy it", + srcamap, srcamap->am_ref, 0, 0); + /* - * looks like we need to copy the map. + * Allocate a new amap (note: not initialised, no lock set, etc). */ - UVMHIST_LOG(maphist," amap=%p, ref=%d, must copy it", - entry->aref.ar_amap, entry->aref.ar_amap->am_ref, 0, 0); - AMAP_B2SLOT(slots, entry->end - entry->start); + AMAP_B2SLOT(slots, len); amap = amap_alloc1(slots, 0, waitf); if (amap == NULL) { UVMHIST_LOG(maphist, " amap_alloc1 failed", 0,0,0,0); return; } - srcamap = entry->aref.ar_amap; + amap_lock(srcamap); /* - * need to double check reference count now that we've got the - * src amap locked down. the reference count could have - * changed while we were allocating. if the reference count - * dropped down to one we take over the old map rather than - * copying the amap. + * Re-check the reference count with the lock held. If it has + * dropped to one - we can take over the existing map. */ - if (srcamap->am_ref == 1) { /* take it over? */ + if (srcamap->am_ref == 1) { + /* Just take over the existing amap. */ entry->etype &= ~UVM_ET_NEEDSCOPY; - amap->am_ref--; /* drop final reference to map */ - amap_free(amap); /* dispose of new (unused) amap */ amap_unlock(srcamap); + /* Destroy the new (unused) amap. */ + amap->am_ref--; + amap_free(amap); return; } /* - * we must copy it now. + * Copy the slots. Zero the padded part. */ UVMHIST_LOG(maphist, " copying amap now",0, 0, 0, 0); @@ -886,28 +894,30 @@ (amap->am_maxslot - lcv) * sizeof(struct vm_anon *)); /* - * drop our reference to the old amap (srcamap) and unlock. - * we know that the reference count on srcamap is greater than - * one (we checked above), so there is no way we could drop - * the count to zero. [and no need to worry about freeing it] + * Drop our reference to the old amap (srcamap) and unlock. + * Since the reference count on srcamap is greater than one, + * (we checked above), it cannot drop to zero. */ srcamap->am_ref--; - if (srcamap->am_ref == 1 && (srcamap->am_flags & AMAP_SHARED) != 0) - srcamap->am_flags &= ~AMAP_SHARED; /* clear shared flag */ + KASSERT(srcamap->am_ref > 0); + + if (srcamap->am_ref == 1 && (srcamap->am_flags & AMAP_SHARED) != 0) { + srcamap->am_flags &= ~AMAP_SHARED; + } tofree = NULL; #ifdef UVM_AMAP_PPREF if (srcamap->am_ppref && srcamap->am_ppref != PPREF_NONE) { amap_pp_adjref(srcamap, entry->aref.ar_pageoff, - (entry->end - entry->start) >> PAGE_SHIFT, -1, &tofree); + len >> PAGE_SHIFT, -1, &tofree); } #endif uvm_anfree(tofree); amap_unlock(srcamap); /* - * if we referenced any anons then share the source amap's lock. - * otherwise we have nothing in common, so allocate a new one. + * If we referenced any anons, then share the source amap's lock. + * Otherwise, we have nothing in common, so allocate a new one. */ if (amap->am_nused != 0) { @@ -920,7 +930,7 @@ amap_list_insert(amap); /* - * install new amap. + * Install new amap. */ entry->aref.ar_pageoff = 0; @@ -1196,24 +1206,23 @@ } /* - * amap_wiperange: wipe out a range of an amap - * [different from amap_wipeout because the amap is kept intact] + * amap_wiperange: wipe out a range of an amap. + * Note: different from amap_wipeout because the amap is kept intact. * - * => both map and amap must be locked by caller. + * => Both map and amap must be locked by caller. */ void amap_wiperange(struct vm_amap *amap, int slotoff, int slots, struct vm_anon **tofree) { - u_int lcv, stop, curslot, ptr, slotend; - struct vm_anon *anon; + u_int lcv, stop, slotend; bool byanon; KASSERT(mutex_owned(amap->am_lock)); /* - * we can either traverse the amap by am_anon or by am_slots depending - * on which is cheaper. decide now. + * We can either traverse the amap by am_anon or by am_slots. + * Determine which way is less expensive. */ if (slots < amap->am_nused) { @@ -1229,6 +1238,9 @@ } while (lcv < stop) { + struct vm_anon *anon; + u_int curslot, ptr, last; + if (byanon) { curslot = lcv++; /* lcv advances here */ if (amap->am_anon[curslot] == NULL) @@ -1242,6 +1254,7 @@ stop--; /* drop stop, since anon will be removed */ } anon = amap->am_anon[curslot]; + KASSERT(anon->an_lock == amap->am_lock); /* * Remove anon from the amap. @@ -1249,11 +1262,10 @@ amap->am_anon[curslot] = NULL; ptr = amap->am_bckptr[curslot]; - if (ptr != (amap->am_nused - 1)) { - amap->am_slots[ptr] = - amap->am_slots[amap->am_nused - 1]; - amap->am_bckptr[amap->am_slots[ptr]] = - ptr; /* back ptr. */ + last = amap->am_nused - 1; + if (ptr != last) { + amap->am_slots[ptr] = amap->am_slots[last]; + amap->am_bckptr[amap->am_slots[ptr]] = ptr; } amap->am_nused--;