> Date: Thu, 18 Mar 2021 09:26:14 +0100
> From: Martin Pieuchot <[email protected]>
>
> Diff below only touches comments in sys/uvm. It reverts the commit from
> 2014 that turned three line comments into one line comments and sync
> some more block with NetBSD -current. This helps reducing the diff with
> NetBSD.
>
> ok?
A few nits below where I think you change the comments in a way that
is misleading because our implementation differs from NetBSD.
> Index: uvm/uvm_addr.c
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_addr.c,v
> retrieving revision 1.29
> diff -u -p -r1.29 uvm_addr.c
> --- uvm/uvm_addr.c 22 Sep 2020 14:31:08 -0000 1.29
> +++ uvm/uvm_addr.c 17 Mar 2021 09:28:07 -0000
> @@ -65,7 +65,9 @@ struct uaddr_rnd_state {
> #endif
> };
>
> -/* Definition of a pivot in pivot selector. */
> +/*
> + * Definition of a pivot in pivot selector.
> + */
> struct uaddr_pivot {
> vaddr_t addr; /* End of prev. allocation. */
> int expire;/* Best before date. */
> @@ -87,7 +89,11 @@ struct uaddr_pivot_state {
> extern const struct uvm_addr_functions uaddr_kernel_functions;
> struct uvm_addr_state uaddr_kbootstrap;
>
> -/* Support functions. */
> +
> +/*
> + * Support functions.
> + */
> +
> #ifndef SMALL_KERNEL
> struct vm_map_entry *uvm_addr_entrybyspace(struct uaddr_free_rbtree*,
> vsize_t);
> @@ -236,7 +242,9 @@ uvm_addr_fitspace(vaddr_t *min_result, v
> if (fspace - before_gap - after_gap < sz)
> return ENOMEM;
>
> - /* Calculate lowest address. */
> + /*
> + * Calculate lowest address.
> + */
> low_addr += before_gap;
> low_addr = uvm_addr_align_forward(tmp = low_addr, align, offset);
> if (low_addr < tmp) /* Overflow during alignment. */
> @@ -244,7 +252,9 @@ uvm_addr_fitspace(vaddr_t *min_result, v
> if (high_addr - after_gap - sz < low_addr)
> return ENOMEM;
>
> - /* Calculate highest address. */
> + /*
> + * Calculate highest address.
> + */
> high_addr -= after_gap + sz;
> high_addr = uvm_addr_align_backward(tmp = high_addr, align, offset);
> if (high_addr > tmp) /* Overflow during alignment. */
> @@ -341,7 +351,9 @@ uvm_addr_linsearch(struct vm_map *map, s
> (before_gap & PAGE_MASK) == 0 && (after_gap & PAGE_MASK) == 0);
> KASSERT(high + sz > high); /* Check for overflow. */
>
> - /* Hint magic. */
> + /*
> + * Hint magic.
> + */
> if (hint == 0)
> hint = (direction == 1 ? low : high);
> else if (hint > high) {
> @@ -463,6 +475,7 @@ uaddr_destroy(struct uvm_addr_state *uad
> * If hint is set, search will start at the hint position.
> * Only searches forward.
> */
> +
> const struct uvm_addr_functions uaddr_lin_functions = {
> .uaddr_select = &uaddr_lin_select,
> .uaddr_destroy = &uaddr_destroy,
> @@ -489,7 +502,9 @@ uaddr_lin_select(struct vm_map *map, str
> {
> vaddr_t guard_sz;
>
> - /* Deal with guardpages: search for space with one extra page. */
> + /*
> + * Deal with guardpages: search for space with one extra page.
> + */
> guard_sz = ((map->flags & VM_MAP_GUARDPAGES) == 0 ? 0 : PAGE_SIZE);
>
> if (uaddr->uaddr_maxaddr - uaddr->uaddr_minaddr - guard_sz < sz)
> @@ -716,6 +731,7 @@ uaddr_rnd_print(struct uvm_addr_state *u
> /*
> * Kernel allocation bootstrap logic.
> */
> +
> const struct uvm_addr_functions uaddr_kernel_functions = {
> .uaddr_select = &uaddr_kbootstrap_select,
> .uaddr_destroy = &uaddr_kbootstrap_destroy,
> @@ -839,7 +855,9 @@ uaddr_bestfit_select(struct vm_map *map,
> if (entry == NULL)
> return ENOMEM;
>
> - /* Walk the tree until we find an entry that fits. */
> + /*
> + * Walk the tree until we find an entry that fits.
> + */
> while (uvm_addr_fitspace(&min, &max,
> VMMAP_FREE_START(entry), VMMAP_FREE_END(entry),
> sz, align, offset, 0, guardsz) != 0) {
> @@ -848,7 +866,9 @@ uaddr_bestfit_select(struct vm_map *map,
> return ENOMEM;
> }
>
> - /* Return the address that generates the least fragmentation. */
> + /*
> + * Return the address that generates the least fragmentation.
> + */
> *entry_out = entry;
> *addr_out = (min - VMMAP_FREE_START(entry) <=
> VMMAP_FREE_END(entry) - guardsz - sz - max ?
> @@ -1128,7 +1148,9 @@ uaddr_pivot_select(struct vm_map *map, s
> if (pivot->addr == 0 || pivot->entry == NULL || pivot->expire == 0)
> goto expired; /* Pivot is invalid (null or expired). */
>
> - /* Attempt to use the pivot to map the entry. */
> + /*
> + * Attempt to use the pivot to map the entry.
> + */
> entry = pivot->entry;
> if (pivot->dir > 0) {
> if (uvm_addr_fitspace(&min, &max,
> Index: uvm/uvm_amap.c
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_amap.c,v
> retrieving revision 1.87
> diff -u -p -r1.87 uvm_amap.c
> --- uvm/uvm_amap.c 19 Jan 2021 13:21:36 -0000 1.87
> +++ uvm/uvm_amap.c 17 Mar 2021 11:15:29 -0000
> @@ -188,7 +188,7 @@ amap_chunk_free(struct vm_amap *amap, st
> * when enabled, an array of ints is allocated for the pprefs. this
> * array is allocated only when a partial reference is added to the
> * map (either by unmapping part of the amap, or gaining a reference
> - * to only a part of an amap). if the malloc of the array fails
> + * to only a part of an amap). if the allocation of the array fails
> * (M_NOWAIT), then we set the array pointer to PPREF_NONE to indicate
> * that we tried to do ppref's but couldn't alloc the array so just
> * give up (after all, this is an optional feature!).
> @@ -209,12 +209,14 @@ amap_chunk_free(struct vm_amap *amap, st
> * chunk. note that the "plus one" part is needed because a reference
> * count of zero is neither positive or negative (need a way to tell
> * if we've got one zero or a bunch of them).
> - *
> + *
> * here are some in-line functions to help us.
> */
>
> /*
> * pp_getreflen: get the reference and length for a specific offset
> + *
> + * => ppref's amap must be locked
> */
> static inline void
> pp_getreflen(int *ppref, int offset, int *refp, int *lenp)
> @@ -231,6 +233,8 @@ pp_getreflen(int *ppref, int offset, int
>
> /*
> * pp_setreflen: set the reference and length for a specific offset
> + *
> + * => ppref's amap must be locked
> */
> static inline void
> pp_setreflen(int *ppref, int offset, int ref, int len)
> @@ -242,7 +246,7 @@ pp_setreflen(int *ppref, int offset, int
> ppref[offset+1] = len;
> }
> }
> -#endif
> +#endif /* UVM_AMAP_PPREF */
>
> /*
> * amap_init: called at boot time to init global amap data structures
> @@ -276,8 +280,9 @@ amap_init(void)
> }
>
> /*
> - * 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.
> + *
> + * => Note: lock is not set.
> */
> static inline struct vm_amap *
> amap_alloc1(int slots, int waitf, int lazyalloc)
> @@ -408,6 +413,7 @@ amap_lock_alloc(struct vm_amap *amap)
> *
> * => caller should ensure sz is a multiple of PAGE_SIZE
> * => reference count to new amap is set to one
> + * => new amap is returned unlocked
> */
> struct vm_amap *
> amap_alloc(vaddr_t sz, int waitf, int lazyalloc)
> @@ -432,6 +438,7 @@ amap_alloc(vaddr_t sz, int waitf, int la
> /*
> * amap_free: free an amap
> *
> + * => the amap must be unlocked
> * => the amap should have a zero reference count and be empty
> */
> void
> @@ -466,11 +473,9 @@ amap_free(struct vm_amap *amap)
> /*
> * 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 == 1)
> + * => Called from amap_unref(), when reference count drops to zero.
> * => amap must be locked.
> */
> -
> void
> amap_wipeout(struct vm_amap *amap)
> {
> @@ -483,7 +488,9 @@ amap_wipeout(struct vm_amap *amap)
> KASSERT(amap->am_ref == 0);
>
> if (__predict_false((amap->am_flags & AMAP_SWAPOFF) != 0)) {
> - /* amap_swap_off will call us again. */
> + /*
> + * Note: amap_swap_off() will call us again.
> + */
> amap_unlock(amap);
> return;
> }
> @@ -503,12 +510,11 @@ amap_wipeout(struct vm_amap *amap)
> panic("amap_wipeout: corrupt amap");
> KASSERT(anon->an_lock == amap->am_lock);
>
> + /*
> + * Drop the reference.
> + */
> refs = --anon->an_ref;
> if (refs == 0) {
> - /*
> - * we had the last reference to a vm_anon.
> - * free it.
> - */
> uvm_anfree_list(anon, &pgl);
> }
> }
> @@ -516,7 +522,9 @@ amap_wipeout(struct vm_amap *amap)
> /* free the pages */
> uvm_pglistfree(&pgl);
>
> - /* now we free the map */
> + /*
> + * Finally, destroy the amap.
> + */
> amap->am_ref = 0; /* ... was one */
> amap->am_nused = 0;
> amap_unlock(amap);
> @@ -526,10 +534,10 @@ amap_wipeout(struct vm_amap *amap)
> /*
> * amap_copy: ensure that a map entry's "needs_copy" flag is false
> * by copying the amap if necessary.
> - *
> + *
> * => an entry with a null amap pointer will get a new (blank) one.
> - * => the map that the map entry blocks to must be locked by caller.
> - * => the amap (if any) currently attached to the entry must be unlocked.
> + * => the map that the map entry belongs to must be locked by caller.
> + * => the amap currently attached to "entry" (if any) must be unlocked.
> * => if canchunk is true, then we may clip the entry into a chunk
> * => "startva" and "endva" are used only if canchunk is true. they are
> * used to limit chunking (e.g. if you have a large space that you
> @@ -550,14 +558,16 @@ amap_copy(struct vm_map *map, struct vm_
>
> KASSERT(map != kernel_map); /* we use sleeping locks */
>
> - /* 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) {
> /*
> - * 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 we cannot chunk the amap, allocate it in a way
> + * If we cannot chunk the amap, allocate it in a way
> * that makes it grow or shrink dynamically with
> * the number of slots.
> */
> @@ -584,17 +594,21 @@ amap_copy(struct vm_map *map, struct vm_
> }
>
> /*
> - * 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. the value can only
> - * be one if we have the only reference to the amap
> + * 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) {
> entry->etype &= ~UVM_ET_NEEDSCOPY;
> return;
> }
>
> - /* looks like we need to copy the map. */
> + /*
> + * Allocate a new amap (note: not initialised, etc).
> + */
> AMAP_B2SLOT(slots, entry->end - entry->start);
> if (!UVM_AMAP_SMALL(entry->aref.ar_amap) &&
> entry->aref.ar_amap->am_hashshift != 0)
> @@ -607,20 +621,22 @@ amap_copy(struct vm_map *map, struct vm_
> amap_lock(srcamap);
>
> /*
> - * need to double check reference count now. the reference count
> - * could have changed while we were in malloc. 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_unlock(srcamap);
> - amap->am_ref--; /* drop final reference to map */
> - amap_free(amap); /* dispose of new (unused) amap */
> + /* Destroy the new (unused) amap. */
> + amap->am_ref--;
> + amap_free(amap);
> return;
> }
>
> - /* we must copy it now. */
> + /*
> + * Copy the slots. Zero the padded part.
> + */
"Zero the padded part" makes no sense for us since our amap_chunk code
does things different.
> for (lcv = 0; lcv < slots; lcv += n) {
> srcslot = entry->aref.ar_pageoff + lcv;
> i = UVM_AMAP_SLOTIDX(lcv);
> @@ -659,10 +675,9 @@ amap_copy(struct vm_map *map, struct vm_
> }
>
> /*
> - * drop our reference to the old amap (srcamap).
> - * 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 while it is locked.
> */
> srcamap->am_ref--;
> KASSERT(srcamap->am_ref > 0);
> @@ -690,7 +705,9 @@ amap_copy(struct vm_map *map, struct vm_
> if (amap->am_lock == NULL)
> amap_lock_alloc(amap);
>
> - /* install new amap. */
> + /*
> + * Install new amap.
> + */
> entry->aref.ar_pageoff = 0;
> entry->aref.ar_amap = amap;
> entry->etype &= ~UVM_ET_NEEDSCOPY;
> @@ -723,9 +740,9 @@ amap_cow_now(struct vm_map *map, struct
> struct vm_amap_chunk *chunk;
>
> /*
> - * note that if we wait, we must ReStart the "lcv" for loop because
> - * some other process could reorder the anon's in the
> - * am_anon[] array on us.
> + * note that if we unlock the amap then we must ReStart the "lcv" for
> + * loop because some other process could reorder the anon's in the
> + * am_anon[] array on us while the lock is dropped.
> */
> ReStart:
> amap_lock(amap);
> @@ -739,7 +756,10 @@ ReStart:
> pg = anon->an_page;
> KASSERT(anon->an_lock == amap->am_lock);
>
> - /* page must be resident since parent is wired */
> + /*
> + * The old page must be resident since the parent is
> + * wired.
> + */
> KASSERT(pg != NULL);
>
> /*
> @@ -750,7 +770,7 @@ ReStart:
> continue;
>
> /*
> - * if the page is busy then we have to wait for
> + * If the page is busy, then we have to unlock, wait for
> * it and then restart.
> */
> if (pg->pg_flags & PG_BUSY) {
> @@ -760,7 +780,10 @@ ReStart:
> goto ReStart;
> }
>
> - /* 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 != NULL) {
> /* the new anon will share the amap's lock */
> @@ -783,18 +806,18 @@ ReStart:
> }
>
> /*
> - * 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).
> */
> - uvm_pagecopy(pg, npg); /* old -> new */
> - anon->an_ref--; /* can't drop to zero */
> + uvm_pagecopy(pg, npg);
> + anon->an_ref--;
> KASSERT(anon->an_ref > 0);
> - chunk->ac_anon[slot] = nanon; /* replace */
> + chunk->ac_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 | PG_WANTED.
> + * Drop PG_BUSY on new page. Since its owner was write
> + * locked all this time - it cannot be PG_RELEASED or
> + * PG_WANTED.
> */
> atomic_clearbits_int(&npg->pg_flags, PG_BUSY|PG_FAKE);
> UVM_PAGE_OWN(npg, NULL);
> @@ -810,6 +833,8 @@ ReStart:
> * amap_splitref: split a single reference into two separate references
> *
> * => called from uvm_map's clip routines
> + * => origref's map should be locked
> + * => origref->ar_amap should be unlocked (we will lock)
> */
> void
> amap_splitref(struct vm_aref *origref, struct vm_aref *splitref, vaddr_t
> offset)
> @@ -824,12 +849,11 @@ amap_splitref(struct vm_aref *origref, s
>
> amap_lock(amap);
>
> - /* now: we have a valid am_mapped array. */
> if (amap->am_nslot - origref->ar_pageoff - leftslots <= 0)
> panic("amap_splitref: map size check failed");
>
> #ifdef UVM_AMAP_PPREF
> - /* Establish ppref before we add a duplicate reference to the amap.
> */
> + /* Establish ppref before we add a duplicate reference to the amap. */
> if (amap->am_ppref == NULL)
> amap_pp_establish(amap);
> #endif
> @@ -844,7 +868,9 @@ amap_splitref(struct vm_aref *origref, s
> #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 should be locked by caller* => amap should be locked by caller
> */
> void
> amap_pp_establish(struct vm_amap *amap)
> @@ -854,13 +880,12 @@ amap_pp_establish(struct vm_amap *amap)
> amap->am_ppref = mallocarray(amap->am_nslot, sizeof(int),
> M_UVMAMAP, M_NOWAIT|M_ZERO);
>
> - /* if we fail then we just won't use ppref for this amap */
> 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;
> }
>
> - /* init ppref */
> pp_setreflen(amap->am_ppref, 0, amap->am_ref, amap->am_nslot);
> }
>
> @@ -868,7 +893,8 @@ amap_pp_establish(struct vm_amap *amap)
> * amap_pp_adjref: adjust reference count to a part of an amap using the
> * per-page reference count array.
> *
> - * => 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)
> @@ -883,8 +909,7 @@ amap_pp_adjref(struct vm_amap *amap, int
> 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) {
> pp_getreflen(ppref, lcv, &ref, &len);
> @@ -898,17 +923,17 @@ amap_pp_adjref(struct vm_amap *amap, int
> 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.
> + /*
> + * 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;
> }
>
> /*
> - * 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.
> */
> if (lcv != curslot)
> @@ -972,12 +997,19 @@ amap_wiperange_chunk(struct vm_amap *ama
> if (refs == 0) {
> uvm_anfree(anon);
> }
> - }
> +
> + /*
> + * done with this anon, next ...!
> + */
> +
> + } /* end of 'for' loop */
> }
>
> /*
> - * 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.
> */
> void
> amap_wiperange(struct vm_amap *amap, int slotoff, int slots)
> @@ -991,8 +1023,8 @@ amap_wiperange(struct vm_amap *amap, int
> endbucket = UVM_AMAP_BUCKET(amap, slotoff + slots - 1);
>
> /*
> - * we can either traverse the amap by am_chunks or by am_buckets
> - * depending on which is cheaper. decide now.
> + * We can either traverse the amap by am_chunks or by am_buckets.
> + * Determine which way is less expensive.
> */
> if (UVM_AMAP_SMALL(amap))
> amap_wiperange_chunk(amap, &amap->am_small, slotoff, slots);
> @@ -1110,7 +1142,9 @@ nextamap:
> }
>
> /*
> - * amap_lookup: look up a page in an amap
> + * amap_lookup: look up a page in an amap.
> + *
> + * => amap should be locked by caller.
> */
> struct vm_anon *
> amap_lookup(struct vm_aref *aref, vaddr_t offset)
> @@ -1131,8 +1165,9 @@ amap_lookup(struct vm_aref *aref, vaddr_
> }
>
> /*
> - * amap_lookups: look up a range of pages in an amap
> + * amap_lookups: look up a range of pages in an amap.
> *
> + * => amap should be locked by caller.
> * => XXXCDC: this interface is biased toward array-based amaps. fix.
> */
> void
> @@ -1184,9 +1219,10 @@ amap_populate(struct vm_aref *aref, vadd
> }
>
> /*
> - * amap_add: add (or replace) a page to an amap
> + * amap_add: add (or replace) a page to an amap.
> *
> - * => returns 0 if adding the page was successful or 1 when not.
> + * => amap should be locked by caller.
> + * => anon must have the lock associated with this amap.
> */
> int
> amap_add(struct vm_aref *aref, vaddr_t offset, struct vm_anon *anon,
> @@ -1228,7 +1264,9 @@ amap_add(struct vm_aref *aref, vaddr_t o
> }
>
> /*
> - * amap_unadd: remove a page from an amap
> + * amap_unadd: remove a page from an amap.
> + *
> + * => amap should be locked by caller.
> */
> void
> amap_unadd(struct vm_aref *aref, vaddr_t offset)
> Index: uvm/uvm_anon.c
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_anon.c,v
> retrieving revision 1.52
> diff -u -p -r1.52 uvm_anon.c
> --- uvm/uvm_anon.c 4 Mar 2021 09:00:03 -0000 1.52
> +++ uvm/uvm_anon.c 17 Mar 2021 09:43:47 -0000
> @@ -42,9 +42,6 @@
>
> struct pool uvm_anon_pool;
>
> -/*
> - * allocate anons
> - */
> void
> uvm_anon_init(void)
> {
> @@ -54,7 +51,9 @@ uvm_anon_init(void)
> }
>
> /*
> - * allocate an anon
> + * uvm_analloc: allocate a new anon.
> + *
> + * => anon will have no lock associated.
> */
> struct vm_anon *
> uvm_analloc(void)
> @@ -93,12 +92,10 @@ uvm_anfree_list(struct vm_anon *anon, st
> KASSERT(anon->an_lock != NULL);
>
> /*
> - * if page is busy then we just mark it as released (who ever
> - * has it busy must check for this when they wake up). if the
> - * page is not busy then we can free it now.
> + * If the page is busy, mark it as PG_RELEASED, so
> + * that uvm_anon_release(9) would release it later.
> */
> if ((pg->pg_flags & PG_BUSY) != 0) {
> - /* tell them to dump it when done */
> atomic_setbits_int(&pg->pg_flags, PG_RELEASED);
> rw_obj_hold(anon->an_lock);
> return;
> @@ -127,13 +124,11 @@ uvm_anfree_list(struct vm_anon *anon, st
> }
> anon->an_lock = NULL;
>
> - /* free any swap resources. */
> - uvm_anon_dropswap(anon);
> -
> /*
> - * now that we've stripped the data areas from the anon, free the anon
> - * itself!
> + * Free any swap resources, leave a page replacement hint.
> */
> + uvm_anon_dropswap(anon);
> +
> KASSERT(anon->an_page == NULL);
> KASSERT(anon->an_swslot == 0);
>
> @@ -154,9 +149,10 @@ uvm_anwait(void)
> }
>
> /*
> - * fetch an anon's page.
> + * uvm_anon_pagein: fetch an anon's page.
> *
> - * => returns TRUE if pagein was aborted due to lack of memory.
> + * => anon must be locked, and is unlocked upon return.
> + * => returns true if pagein was aborted due to lack of memory.
> */
>
> boolean_t
> @@ -168,20 +164,26 @@ uvm_anon_pagein(struct vm_amap *amap, st
> KASSERT(rw_write_held(anon->an_lock));
> KASSERT(anon->an_lock == amap->am_lock);
>
> + /*
> + * Get the page of the anon.
> + */
> rv = uvmfault_anonget(NULL, amap, anon);
>
> switch (rv) {
> case VM_PAGER_OK:
> KASSERT(rw_write_held(anon->an_lock));
> break;
> +
> case VM_PAGER_ERROR:
> case VM_PAGER_REFAULT:
> +
> /*
> - * nothing more to do on errors.
> - * VM_PAGER_REFAULT can only mean that the anon was freed,
> - * so again there's nothing to do.
> + * Nothing more to do on errors.
> + * VM_PAGER_REFAULT means that the anon was freed.
> */
> +
> return FALSE;
> +
> default:
> #ifdef DIAGNOSTIC
> panic("anon_pagein: uvmfault_anonget -> %d", rv);
> @@ -191,8 +193,7 @@ uvm_anon_pagein(struct vm_amap *amap, st
> }
>
> /*
> - * ok, we've got the page now.
> - * mark it as dirty, clear its swslot and un-busy it.
> + * Mark the page as dirty and clear its swslot.
> */
> pg = anon->an_page;
> if (anon->an_swslot > 0) {
> @@ -201,7 +202,9 @@ uvm_anon_pagein(struct vm_amap *amap, st
> anon->an_swslot = 0;
> atomic_clearbits_int(&pg->pg_flags, PG_CLEAN);
>
> - /* deactivate the page (to put it on a page queue) */
> + /*
> + * Deactivate the page (to put it on a page queue).
> + */
> pmap_clear_reference(pg);
> pmap_page_protect(pg, PROT_NONE);
> uvm_lock_pageq();
> @@ -213,7 +216,7 @@ uvm_anon_pagein(struct vm_amap *amap, st
> }
>
> /*
> - * uvm_anon_dropswap: release any swap resources from this anon.
> + * uvm_anon_dropswap: release any swap resources from this anon.
> *
> * => anon must be locked or have a reference count of 0.
> */
> Index: uvm/uvm_aobj.c
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_aobj.c,v
> retrieving revision 1.91
> diff -u -p -r1.91 uvm_aobj.c
> --- uvm/uvm_aobj.c 4 Mar 2021 09:00:03 -0000 1.91
> +++ uvm/uvm_aobj.c 17 Mar 2021 11:51:11 -0000
> @@ -48,56 +48,45 @@
> #include <uvm/uvm.h>
>
> /*
> - * an aobj manages anonymous-memory backed uvm_objects. in addition
> - * to keeping the list of resident pages, it also keeps a list of
> - * allocated swap blocks. depending on the size of the aobj this list
> - * of allocated swap blocks is either stored in an array (small objects)
> - * or in a hash table (large objects).
> + * An anonymous UVM object (aobj) manages anonymous-memory. In addition to
> + * keeping the list of resident pages, it may also keep a list of allocated
> + * swap blocks. Depending on the size of the object, this list is either
> + * stored in an array (small objects) or in a hash table (large objects).
> */
>
> /*
> - * local structures
> - */
> -
> -/*
> - * for hash tables, we break the address space of the aobj into blocks
> - * of UAO_SWHASH_CLUSTER_SIZE pages. we require the cluster size to
> - * be a power of two.
> + * Note: for hash tables, we break the address space of the aobj into blocks
> + * of UAO_SWHASH_CLUSTER_SIZE pages, which shall be a power of two.
> */
> #define UAO_SWHASH_CLUSTER_SHIFT 4
> #define UAO_SWHASH_CLUSTER_SIZE (1 << UAO_SWHASH_CLUSTER_SHIFT)
>
> -/* get the "tag" for this page index */
> +/* Get the "tag" for this page index. */
> #define UAO_SWHASH_ELT_TAG(PAGEIDX) \
> ((PAGEIDX) >> UAO_SWHASH_CLUSTER_SHIFT)
>
> -/* given an ELT and a page index, find the swap slot */
> +/* Given an ELT and a page index, find the swap slot. */
> #define UAO_SWHASH_ELT_PAGESLOT_IDX(PAGEIDX) \
> ((PAGEIDX) & (UAO_SWHASH_CLUSTER_SIZE - 1))
> #define UAO_SWHASH_ELT_PAGESLOT(ELT, PAGEIDX) \
> ((ELT)->slots[(PAGEIDX) & (UAO_SWHASH_CLUSTER_SIZE - 1)])
>
> -/* given an ELT, return its pageidx base */
> +/* Given an ELT, return its pageidx base. */
> #define UAO_SWHASH_ELT_PAGEIDX_BASE(ELT) \
> ((ELT)->tag << UAO_SWHASH_CLUSTER_SHIFT)
>
> -/*
> - * the swhash hash function
> - */
> +/* The hash function. */
> #define UAO_SWHASH_HASH(AOBJ, PAGEIDX) \
> (&(AOBJ)->u_swhash[(((PAGEIDX) >> UAO_SWHASH_CLUSTER_SHIFT) \
> & (AOBJ)->u_swhashmask)])
>
> /*
> - * the swhash threshold determines if we will use an array or a
> + * The threshold which determines whether we will use an array or a
> * hash table to store the list of allocated swap blocks.
> */
> -
> #define UAO_SWHASH_THRESHOLD (UAO_SWHASH_CLUSTER_SIZE * 4)
>
> -/*
> - * the number of buckets in a swhash, with an upper bound
> - */
> +/* The number of buckets in a hash, with an upper bound. */
> #define UAO_SWHASH_MAXBUCKETS 256
> #define UAO_SWHASH_BUCKETS(pages) \
> (min((pages) >> UAO_SWHASH_CLUSTER_SHIFT, UAO_SWHASH_MAXBUCKETS))
> @@ -149,14 +138,8 @@ struct uvm_aobj {
> LIST_ENTRY(uvm_aobj) u_list; /* global list of aobjs */
> };
>
> -/*
> - * uvm_aobj_pool: pool of uvm_aobj structures
> - */
> struct pool uvm_aobj_pool;
>
> -/*
> - * local functions
> - */
> static struct uao_swhash_elt *uao_find_swhash_elt(struct uvm_aobj *, int,
> boolean_t);
> static int uao_find_swslot(struct uvm_aobj *, int);
> @@ -223,17 +206,20 @@ uao_find_swhash_elt(struct uvm_aobj *aob
> swhash = UAO_SWHASH_HASH(aobj, pageidx); /* first hash to get bucket */
> page_tag = UAO_SWHASH_ELT_TAG(pageidx); /* tag to search for */
>
> - /* now search the bucket for the requested tag */
> + /*
> + * now search the bucket for the requested tag
> + */
> LIST_FOREACH(elt, swhash, list) {
> if (elt->tag == page_tag)
> return(elt);
> }
>
> - /* fail now if we are not allowed to create a new entry in the bucket */
> if (!create)
> return NULL;
>
> - /* allocate a new entry for the bucket and init/insert it in */
> + /*
> + * allocate a new entry for the bucket and init/insert it in
> + */
> elt = pool_get(&uao_swhash_elt_pool, PR_NOWAIT | PR_ZERO);
> /*
> * XXX We cannot sleep here as the hash table might disappear
> @@ -258,11 +244,15 @@ inline static int
> uao_find_swslot(struct uvm_aobj *aobj, int pageidx)
> {
>
> - /* if noswap flag is set, then we never return a slot */
> + /*
> + * if noswap flag is set, then we never return a slot
> + */
> if (aobj->u_flags & UAO_FLAG_NOSWAP)
> return(0);
>
> - /* if hashing, look in hash table. */
> + /*
> + * if hashing, look in hash table.
> + */
> if (aobj->u_pages > UAO_SWHASH_THRESHOLD) {
> struct uao_swhash_elt *elt =
> uao_find_swhash_elt(aobj, pageidx, FALSE);
> @@ -273,7 +263,9 @@ uao_find_swslot(struct uvm_aobj *aobj, i
> return(0);
> }
>
> - /* otherwise, look in the array */
> + /*
> + * otherwise, look in the array
> + */
> return(aobj->u_swslots[pageidx]);
> }
>
> @@ -281,6 +273,8 @@ uao_find_swslot(struct uvm_aobj *aobj, i
> * uao_set_swslot: set the swap slot for a page in an aobj.
> *
> * => setting a slot to zero frees the slot
> + * => we return the old slot number, or -1 if we failed to allocate
> + * memory to record the new slot number
> */
> int
> uao_set_swslot(struct uvm_object *uobj, int pageidx, int slot)
> @@ -290,18 +284,22 @@ uao_set_swslot(struct uvm_object *uobj,
>
> KERNEL_ASSERT_LOCKED();
>
> - /* if noswap flag is set, then we can't set a slot */
> + /*
> + * if noswap flag is set, then we can't set a slot
> + */
> if (aobj->u_flags & UAO_FLAG_NOSWAP) {
> +
I don't see a reason tp introduce a blank line here.
> if (slot == 0)
> return(0); /* a clear is ok */
>
> /* but a set is not */
> printf("uao_set_swslot: uobj = %p\n", uobj);
> - panic("uao_set_swslot: attempt to set a slot"
> - " on a NOSWAP object");
> + panic("uao_set_swslot: attempt to set a slot on a NOSWAP object");
> }
>
> - /* are we using a hash table? if so, add it in the hash. */
> + /*
> + * are we using a hash table? if so, add it in the hash.
> + */
> if (aobj->u_pages > UAO_SWHASH_THRESHOLD) {
> /*
> * Avoid allocating an entry just to free it again if
> @@ -322,12 +320,11 @@ uao_set_swslot(struct uvm_object *uobj,
> * now adjust the elt's reference counter and free it if we've
> * dropped it to zero.
> */
> - /* an allocation? */
> if (slot) {
> if (oldslot == 0)
> elt->count++;
> - } else { /* freeing slot ... */
> - if (oldslot) /* to be safe */
> + } else {
> + if (oldslot)
> elt->count--;
>
> if (elt->count == 0) {
> @@ -335,7 +332,7 @@ uao_set_swslot(struct uvm_object *uobj,
> pool_put(&uao_swhash_elt_pool, elt);
> }
> }
> - } else {
> + } else {
> /* we are using an array */
> oldslot = aobj->u_swslots[pageidx];
> aobj->u_swslots[pageidx] = slot;
> @@ -393,12 +390,16 @@ uao_free(struct uvm_aobj *aobj)
> } else {
> int i;
>
> - /* free the array */
> + /*
> + * free the array
> + */
> +
> for (i = 0; i < aobj->u_pages; i++) {
> int slot = aobj->u_swslots[i];
>
> if (slot) {
> uvm_swap_free(slot, 1);
> +
> /* this page is no longer only in swap. */
> atomic_dec_int(&uvmexp.swpgonly);
> }
> @@ -406,7 +407,9 @@ uao_free(struct uvm_aobj *aobj)
> free(aobj->u_swslots, M_UVMAOBJ, aobj->u_pages * sizeof(int));
> }
>
> - /* finally free the aobj itself */
> + /*
> + * finally free the aobj itself
> + */
> pool_put(&uvm_aobj_pool, aobj);
> }
>
> @@ -702,36 +705,39 @@ uao_grow(struct uvm_object *uobj, int pa
> struct uvm_object *
> uao_create(vsize_t size, int flags)
> {
> - static struct uvm_aobj kernel_object_store; /* home of kernel_object */
> - static int kobj_alloced = 0; /* not allocated yet */
> + static struct uvm_aobj kernel_object_store;
> + static int kobj_alloced = 0;
> int pages = round_page(size) >> PAGE_SHIFT;
> int refs = UVM_OBJ_KERN;
> int mflags;
> struct uvm_aobj *aobj;
>
> - /* malloc a new aobj unless we are asked for the kernel object */
> - if (flags & UAO_FLAG_KERNOBJ) { /* want kernel object? */
> + /*
> + * Allocate a new aobj, unless kernel object is requested.
> + */
> + if (flags & UAO_FLAG_KERNOBJ) {
> if (kobj_alloced)
> panic("uao_create: kernel object already allocated");
>
> aobj = &kernel_object_store;
> aobj->u_pages = pages;
> - aobj->u_flags = UAO_FLAG_NOSWAP; /* no swap to start */
> - /* we are special, we never die */
> + aobj->u_flags = UAO_FLAG_NOSWAP;
> kobj_alloced = UAO_FLAG_KERNOBJ;
> } else if (flags & UAO_FLAG_KERNSWAP) {
> aobj = &kernel_object_store;
> if (kobj_alloced != UAO_FLAG_KERNOBJ)
> panic("uao_create: asked to enable swap on kernel object");
> kobj_alloced = UAO_FLAG_KERNSWAP;
> - } else { /* normal object */
> + } else {
> aobj = pool_get(&uvm_aobj_pool, PR_WAITOK);
> aobj->u_pages = pages;
> - aobj->u_flags = 0; /* normal object */
> - refs = 1; /* normal object so 1 ref */
> + aobj->u_flags = 0;
> + refs = 1;
> }
>
> - /* allocate hash/array if necessary */
> + /*
> + * allocate hash/array if necessary
> + */
> if (flags == 0 || (flags & (UAO_FLAG_KERNSWAP | UAO_FLAG_CANFAIL))) {
> if (flags)
> mflags = M_NOWAIT;
> @@ -768,9 +774,14 @@ uao_create(vsize_t size, int flags)
> }
> }
>
> + /*
> + * Initialise UVM object.
> + */
> uvm_objinit(&aobj->u_obj, &aobj_pager, refs);
>
> - /* now that aobj is ready, add it to the global list */
> + /*
> + * now that aobj is ready, add it to the global list
> + */
> mtx_enter(&uao_list_lock);
> LIST_INSERT_HEAD(&uao_list, aobj, u_list);
> mtx_leave(&uao_list_lock);
> @@ -799,7 +810,7 @@ uao_init(void)
> }
>
> /*
> - * uao_reference: add a ref to an aobj
> + * uao_reference: hold a reference to an anonymous UVM object.
> */
> void
> uao_reference(struct uvm_object *uobj)
> @@ -808,23 +819,20 @@ uao_reference(struct uvm_object *uobj)
> uao_reference_locked(uobj);
> }
>
> -/*
> - * uao_reference_locked: add a ref to an aobj
> - */
> void
> uao_reference_locked(struct uvm_object *uobj)
> {
>
> - /* kernel_object already has plenty of references, leave it alone. */
> + /* Kernel object is persistent. */
> if (UVM_OBJ_IS_KERN_OBJECT(uobj))
> return;
>
> - uobj->uo_refs++; /* bump! */
> + uobj->uo_refs++;
> }
>
>
> /*
> - * uao_detach: drop a reference to an aobj
> + * uao_detach: drop a reference to an anonymous UVM object.
> */
> void
> uao_detach(struct uvm_object *uobj)
> @@ -845,26 +853,34 @@ uao_detach_locked(struct uvm_object *uob
> struct uvm_aobj *aobj = (struct uvm_aobj *)uobj;
> struct vm_page *pg;
>
> - /* detaching from kernel_object is a noop. */
> + /*
> + * Detaching from kernel_object is a NOP.
> + */
> if (UVM_OBJ_IS_KERN_OBJECT(uobj)) {
> return;
> }
>
> - uobj->uo_refs--; /* drop ref! */
> - if (uobj->uo_refs) { /* still more refs? */
> + /*
> + * Drop the reference. If it was the last one, destroy the object.
> + */
> + uobj->uo_refs--;
> + if (uobj->uo_refs) {
> return;
> }
>
> - /* remove the aobj from the global list. */
> + /*
> + * Remove the aobj from the global list.
> + */
> mtx_enter(&uao_list_lock);
> LIST_REMOVE(aobj, u_list);
> mtx_leave(&uao_list_lock);
>
> /*
> - * Free all pages left in the object. If they're busy, wait
> - * for them to become available before we kill it.
> - * Release swap resources then free the page.
> - */
> + * Free all the pages left in the aobj. For each page, when the
> + * page is no longer busy (and thus after any disk I/O that it is
> + * involved in is complete), release any swap resources and free
> + * the page itself.
> + */
> uvm_lock_pageq();
> while((pg = RBT_ROOT(uvm_objtree, &uobj->memt)) != NULL) {
> if (pg->pg_flags & PG_BUSY) {
> @@ -880,12 +896,14 @@ uao_detach_locked(struct uvm_object *uob
> }
> uvm_unlock_pageq();
>
> - /* finally, free the rest. */
> + /*
> + * Finally, free the anonymous UVM object itself.
> + */
> uao_free(aobj);
> }
>
> /*
> - * uao_flush: "flush" pages out of a uvm object
> + * uao_flush: flush pages out of a uvm object
> *
> * => if PGO_CLEANIT is not set, then we will not block.
> * => if PGO_ALLPAGE is set, then all pages in the object are valid targets
> @@ -958,15 +976,11 @@ uao_flush(struct uvm_object *uobj, voff_
> /* FALLTHROUGH */
> case PGO_DEACTIVATE:
> deactivate_it:
> - /* skip the page if it's wired */
> if (pp->wire_count != 0)
> continue;
>
> uvm_lock_pageq();
> - /* zap all mappings for the page. */
> pmap_page_protect(pp, PROT_NONE);
> -
> - /* ...and deactivate the page. */
> uvm_pagedeactivate(pp);
> uvm_unlock_pageq();
>
> @@ -983,9 +997,16 @@ uao_flush(struct uvm_object *uobj, voff_
> if (pp->wire_count != 0)
> continue;
>
> - /* zap all mappings for the page. */
> + /*
> + * free the swap slot and the page.
> + */
> pmap_page_protect(pp, PROT_NONE);
>
> + /*
> + * freeing swapslot here is not strictly necessary.
> + * however, leaving it here doesn't save much
> + * because we need to update swap accounting anyway.
> + */
> uao_dropswap(uobj, pp->offset >> PAGE_SHIFT);
> uvm_lock_pageq();
> uvm_pagefree(pp);
> @@ -1029,12 +1050,17 @@ uao_get(struct uvm_object *uobj, voff_t
>
> KERNEL_ASSERT_LOCKED();
>
> - /* get number of pages */
> + /*
> + * get number of pages
> + */
> maxpages = *npagesp;
>
> - /* step 1: handled the case where fault data structures are locked. */
> if (flags & PGO_LOCKED) {
> - /* step 1a: get pages that are already resident. */
> + /*
> + * step 1a: get pages that are already resident. only do
> + * this if the data structures are locked (i.e. the first
> + * time through).
> + */
>
> done = TRUE; /* be optimistic */
> gotpages = 0; /* # of pages we got so far */
> @@ -1065,7 +1091,9 @@ uao_get(struct uvm_object *uobj, voff_t
> }
> }
>
> - /* to be useful must get a non-busy page */
> + /*
> + * to be useful must get a non-busy page
> + */
> if (ptmp == NULL ||
> (ptmp->pg_flags & PG_BUSY) != 0) {
> if (lcv == centeridx ||
> @@ -1076,10 +1104,8 @@ uao_get(struct uvm_object *uobj, voff_t
> }
>
> /*
> - * useful page: busy it and plug it in our
> - * result array
> + * useful page: plug it in our result array
> */
> - /* caller must un-busy this page */
> atomic_setbits_int(&ptmp->pg_flags, PG_BUSY);
> UVM_PAGE_OWN(ptmp, "uao_get1");
> pps[lcv] = ptmp;
> @@ -1146,8 +1172,7 @@ uao_get(struct uvm_object *uobj, voff_t
> /* out of RAM? */
> if (ptmp == NULL) {
> uvm_wait("uao_getpage");
> - /* goto top of pps while loop */
> - continue;
> + continue;
> }
>
> /*
> @@ -1169,12 +1194,10 @@ uao_get(struct uvm_object *uobj, voff_t
> tsleep_nsec(ptmp, PVM, "uao_get", INFSLP);
> continue; /* goto top of pps while loop */
> }
> -
> - /*
> - * if we get here then the page has become resident and
> - * unbusy between steps 1 and 2. we busy it now (so we
> - * own it) and set pps[lcv] (so that we exit the while
> - * loop).
> +
> + /*
> + * if we get here then the page is resident and
> + * unbusy. we busy it now (so we own it).
> */
> /* we own it, caller must un-busy */
> atomic_setbits_int(&ptmp->pg_flags, PG_BUSY);
> @@ -1200,10 +1223,14 @@ uao_get(struct uvm_object *uobj, voff_t
> /* page hasn't existed before, just zero it. */
> uvm_pagezero(ptmp);
> } else {
> - /* page in the swapped-out page. */
> + /*
> + * page in the swapped-out page.
> + */
> rv = uvm_swap_get(ptmp, swslot, PGO_SYNCIO);
>
> - /* I/O done. check for errors. */
> + /*
> + * I/O done. check for errors.
> + */
> if (rv != VM_PAGER_OK) {
> /*
> * remove the swap slot from the aobj
> @@ -1228,18 +1255,16 @@ uao_get(struct uvm_object *uobj, voff_t
> }
> }
>
> - /*
> + /*
> * we got the page! clear the fake flag (indicates valid
> * data now in page) and plug into our result array. note
> - * that page is still busy.
> + * that page is still busy.
> *
> * it is the callers job to:
> * => check if the page is released
> * => unbusy the page
> * => activate the page
> */
> -
> - /* data is valid ... */
> atomic_clearbits_int(&ptmp->pg_flags, PG_FAKE);
> pmap_clear_modify(ptmp); /* ... and clean */
> pps[lcv] = ptmp;
> @@ -1274,7 +1299,9 @@ uao_swap_off(int startslot, int endslot)
> {
> struct uvm_aobj *aobj, *nextaobj, *prevaobj = NULL;
>
> - /* walk the list of all aobjs. */
> + /*
> + * Walk the list of all anonymous UVM objects.
> + */
> mtx_enter(&uao_list_lock);
>
> for (aobj = LIST_FIRST(&uao_list);
> @@ -1325,7 +1352,9 @@ uao_swap_off(int startslot, int endslot)
> prevaobj = aobj;
> }
>
> - /* done with traversal, unlock the list */
> + /*
> + * done with traversal, unlock the list
> + */
> mtx_leave(&uao_list_lock);
> if (prevaobj) {
> uao_detach_locked(&prevaobj->u_obj);
> @@ -1357,8 +1386,10 @@ restart:
> for (i = 0; i < UAO_SWHASH_CLUSTER_SIZE; i++) {
> int slot = elt->slots[i];
>
> - /* if slot isn't in range, skip it. */
> - if (slot < startslot ||
> + /*
> + * if the slot isn't in range, skip it.
> + */
> + if (slot < startslot ||
> slot >= endslot) {
> continue;
> }
> @@ -1384,12 +1415,16 @@ restart:
> for (i = 0; i < aobj->u_pages; i++) {
> int slot = aobj->u_swslots[i];
>
> - /* if the slot isn't in range, skip it */
> + /*
> + * if the slot isn't in range, skip it
> + */
> if (slot < startslot || slot >= endslot) {
> continue;
> }
>
> - /* process the page. */
> + /*
> + * process the page.
> + */
> rv = uao_pagein_page(aobj, i);
> if (rv) {
> return rv;
> @@ -1401,8 +1436,9 @@ restart:
> }
>
> /*
> - * page in a page from an aobj. used for swap_off.
> - * returns TRUE if pagein was aborted due to lack of memory.
> + * uao_pagein_page: page in a single page from an anonymous UVM object.
> + *
> + * => Returns TRUE if pagein was aborted due to lack of memory.
> */
> static boolean_t
> uao_pagein_page(struct uvm_aobj *aobj, int pageidx)
> @@ -1438,7 +1474,9 @@ uao_pagein_page(struct uvm_aobj *aobj, i
> atomic_clearbits_int(&pg->pg_flags, PG_BUSY|PG_CLEAN|PG_FAKE);
> UVM_PAGE_OWN(pg, NULL);
>
> - /* deactivate the page (to put it on a page queue). */
> + /*
> + * deactivate the page (to put it on a page queue).
> + */
> pmap_clear_reference(pg);
> uvm_lock_pageq();
> uvm_pagedeactivate(pg);
> Index: uvm/uvm_device.c
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_device.c,v
> retrieving revision 1.60
> diff -u -p -r1.60 uvm_device.c
> --- uvm/uvm_device.c 6 Nov 2020 11:52:39 -0000 1.60
> +++ uvm/uvm_device.c 17 Mar 2021 11:56:09 -0000
> @@ -79,6 +79,11 @@ const struct uvm_pagerops uvm_deviceops
> };
>
> /*
> + * the ops!
> + */
> +
> +
> +/*
> * udv_attach
> *
> * get a VM object that is associated with a device. allocate a new
> @@ -97,14 +102,20 @@ udv_attach(dev_t device, vm_prot_t acces
> struct uvm_object *obj;
> #endif
>
> - /* before we do anything, ensure this device supports mmap */
> + /*
> + * before we do anything, ensure this device supports mmap
> + */
> +
> mapfn = cdevsw[major(device)].d_mmap;
> if (mapfn == NULL ||
> mapfn == (paddr_t (*)(dev_t, off_t, int)) enodev ||
> mapfn == (paddr_t (*)(dev_t, off_t, int)) nullop)
> return(NULL);
>
> - /* Negative offsets on the object are not allowed. */
> + /*
> + * Negative offsets on the object are not allowed.
> + */
> +
> if (off < 0)
> return(NULL);
>
> @@ -120,28 +131,41 @@ udv_attach(dev_t device, vm_prot_t acces
> *
> * XXX clobbers off and size, but nothing else here needs them.
> */
> +
> while (size != 0) {
> if ((*mapfn)(device, off, accessprot) == -1)
> return (NULL);
> off += PAGE_SIZE; size -= PAGE_SIZE;
> }
>
> - /* keep looping until we get it */
> + /*
> + * keep looping until we get it
> + */
> +
> for (;;) {
> - /* first, attempt to find it on the main list */
> +
> + /*
> + * first, attempt to find it on the main list
> + */
> +
> mtx_enter(&udv_lock);
> LIST_FOREACH(lcv, &udv_list, u_list) {
> if (device == lcv->u_device)
> break;
> }
>
> - /* got it on main list. put a hold on it and unlock udv_lock.
> */
> + /*
> + * got it on main list. put a hold on it and unlock udv_lock.
> + */
> +
> if (lcv) {
> +
> /*
> * if someone else has a hold on it, sleep and start
> * over again. Else, we need take HOLD flag so we
> * don't have to re-order locking here.
> */
> +
> if (lcv->u_flags & UVM_DEVICE_HOLD) {
> lcv->u_flags |= UVM_DEVICE_WANTED;
> msleep_nsec(lcv, &udv_lock, PVM | PNORELOCK,
> @@ -153,7 +177,10 @@ udv_attach(dev_t device, vm_prot_t acces
> lcv->u_flags |= UVM_DEVICE_HOLD;
> mtx_leave(&udv_lock);
>
> - /* bump reference count, unhold, return. */
> + /*
> + * bump reference count, unhold, return.
> + */
> +
> lcv->u_obj.uo_refs++;
>
> mtx_enter(&udv_lock);
> @@ -164,7 +191,10 @@ udv_attach(dev_t device, vm_prot_t acces
> return(&lcv->u_obj);
> }
>
> - /* did not find it on main list. need to malloc a new one. */
> + /*
> + * Did not find it on main list. Need to allocate a new one.
> + */
> +
> mtx_leave(&udv_lock);
> /* NOTE: we could sleep in the following malloc() */
> udv = malloc(sizeof(*udv), M_TEMP, M_WAITOK);
> @@ -229,7 +259,9 @@ udv_detach(struct uvm_object *uobj)
>
> KERNEL_ASSERT_LOCKED();
>
> - /* loop until done */
> + /*
> + * loop until done
> + */
> again:
> if (uobj->uo_refs > 1) {
> uobj->uo_refs--;
> @@ -237,7 +269,10 @@ again:
> }
> KASSERT(uobj->uo_npages == 0 && RBT_EMPTY(uvm_objtree, &uobj->memt));
>
> - /* is it being held? if so, wait until others are done. */
> + /*
> + * is it being held? if so, wait until others are done.
> + */
> +
> mtx_enter(&udv_lock);
> if (udv->u_flags & UVM_DEVICE_HOLD) {
> udv->u_flags |= UVM_DEVICE_WANTED;
> @@ -250,7 +285,10 @@ again:
> goto again;
> }
>
> - /* got it! nuke it now. */
> + /*
> + * got it! nuke it now.
> + */
> +
> LIST_REMOVE(udv, u_list);
> if (udv->u_flags & UVM_DEVICE_WANTED)
> wakeup(udv);
> @@ -310,7 +348,9 @@ udv_fault(struct uvm_faultinfo *ufi, vad
> return(VM_PAGER_ERROR);
> }
>
> - /* get device map function. */
> + /*
> + * get device map function.
> + */
> device = udv->u_device;
> mapfn = cdevsw[major(device)].d_mmap;
>
> @@ -325,7 +365,9 @@ udv_fault(struct uvm_faultinfo *ufi, vad
> /* pmap va = vaddr (virtual address of pps[0]) */
> curr_va = vaddr;
>
> - /* loop over the page range entering in as needed */
> + /*
> + * loop over the page range entering in as needed
> + */
> retval = VM_PAGER_OK;
> for (lcv = 0 ; lcv < npages ; lcv++, curr_offset += PAGE_SIZE,
> curr_va += PAGE_SIZE) {
> Index: uvm/uvm_fault.c
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_fault.c,v
> retrieving revision 1.118
> diff -u -p -r1.118 uvm_fault.c
> --- uvm/uvm_fault.c 12 Mar 2021 14:15:49 -0000 1.118
> +++ uvm/uvm_fault.c 17 Mar 2021 12:15:57 -0000
> @@ -230,24 +230,32 @@ static void
> uvmfault_amapcopy(struct uvm_faultinfo *ufi)
> {
> for (;;) {
> - /* no mapping? give up. */
> + /*
> + * no mapping? give up.
> + */
> if (uvmfault_lookup(ufi, TRUE) == FALSE)
> return;
>
> - /* copy if needed. */
> + /*
> + * copy if needed.
> + */
> if (UVM_ET_ISNEEDSCOPY(ufi->entry))
> amap_copy(ufi->map, ufi->entry, M_NOWAIT,
> UVM_ET_ISSTACK(ufi->entry) ? FALSE : TRUE,
> ufi->orig_rvaddr, ufi->orig_rvaddr + 1);
>
> - /* didn't work? must be out of RAM. sleep. */
> + /*
> + * didn't work? must be out of RAM. unlock and sleep.
> + */
> if (UVM_ET_ISNEEDSCOPY(ufi->entry)) {
> uvmfault_unlockmaps(ufi, TRUE);
> uvm_wait("fltamapcopy");
> continue;
> }
>
> - /* got it! */
> + /*
> + * got it! unlock and return.
> + */
> uvmfault_unlockmaps(ufi, TRUE);
> return;
> }
> @@ -341,11 +349,11 @@ uvmfault_anonget(struct uvm_faultinfo *u
> uvmfault_unlockall(ufi, amap, NULL);
>
> /*
> - * we are passing a PG_BUSY+PG_FAKE+PG_CLEAN
> - * page into the uvm_swap_get function with
> - * all data structures unlocked. note that
> - * it is ok to read an_swslot here because
> - * we hold PG_BUSY on the page.
> + * Pass a PG_BUSY+PG_FAKE+PG_CLEAN page into
> + * the uvm_swap_get() function with all data
> + * structures unlocked. Note that it is OK
> + * to read an_swslot here, because we hold
> + * PG_BUSY on the page.
> */
> counters_inc(uvmexp_counters, pageins);
> error = uvm_swap_get(pg, anon->an_swslot,
> @@ -393,6 +401,9 @@ uvmfault_anonget(struct uvm_faultinfo *u
> if (pg->pg_flags & PG_RELEASED) {
> pmap_page_protect(pg, PROT_NONE);
> KASSERT(anon->an_ref == 0);
> + /*
> + * Released while we had unlocked amap.
> + */
> if (locked)
> uvmfault_unlockall(ufi, NULL, NULL);
> uvm_anon_release(anon); /* frees page for us */
> @@ -418,7 +429,7 @@ uvmfault_anonget(struct uvm_faultinfo *u
> /*
> * Note: page was never !PG_BUSY, so it
> * cannot be mapped and thus no need to
> - * pmap_page_protect it...
> + * pmap_page_protect() it.
> */
> uvm_lock_pageq();
> uvm_pagefree(pg);
> @@ -432,8 +443,7 @@ uvmfault_anonget(struct uvm_faultinfo *u
> }
>
> /*
> - * must be OK, clear modify (already PG_CLEAN)
> - * and activate
> + * We have successfully read the page, activate it.
> */
> pmap_clear_modify(pg);
> uvm_lock_pageq();
> @@ -776,7 +786,9 @@ uvm_fault_check(struct uvm_faultinfo *uf
> if (amap)
> uvmfault_anonflush(*ranons, nback);
>
> - /* flush object? */
> + /*
> + * flush object?
> + */
> if (uobj) {
> voff_t uoff;
>
> @@ -843,7 +855,7 @@ uvm_fault_upper_lookup(struct uvm_faulti
> }
>
> /*
> - * unmapped or center page. check if any anon at this level.
> + * unmapped or center page. check if any anon at this level.
> */
> if (amap == NULL || anons[lcv] == NULL) {
> pages[lcv] = NULL;
> @@ -903,6 +915,7 @@ uvm_fault_upper(struct uvm_faultinfo *uf
> struct vm_page *pg = NULL;
> int error, ret;
>
> + /* locked: maps(read), amap, anon */
> KASSERT(rw_write_held(amap->am_lock));
> KASSERT(anon->an_lock == amap->am_lock);
>
> @@ -1037,11 +1050,15 @@ uvm_fault_upper(struct uvm_faultinfo *uf
> return ERESTART;
> }
>
> - /* ... update the page queues. */
> + /*
> + * ... update the page queues.
> + */
> +
> uvm_lock_pageq();
>
> if (fault_type == VM_FAULT_WIRE) {
> uvm_pagewire(pg);
> +
> /*
> * since the now-wired page cannot be paged out,
> * release its swap resources for others to use.
> @@ -1181,6 +1198,7 @@ uvm_fault_lower(struct uvm_faultinfo *uf
> * (PGO_LOCKED).
> */
> if (uobj == NULL) {
> + /* zero fill; don't care neighbor pages */
> uobjpage = NULL;
> } else {
> uobjpage = uvm_fault_lower_lookup(ufi, flt, pages);
> @@ -1236,7 +1254,10 @@ uvm_fault_lower(struct uvm_faultinfo *uf
> 0, flt->access_type & MASK(ufi->entry), ufi->entry->advice,
> PGO_SYNCIO);
>
> - /* recover from I/O */
> + /*
> + * recover from I/O
> + */
> +
> if (result != VM_PAGER_OK) {
> KASSERT(result != VM_PAGER_PEND);
>
> @@ -1343,7 +1364,10 @@ uvm_fault_lower(struct uvm_faultinfo *uf
> * out of memory resources?
> */
> if (anon == NULL || pg == NULL) {
> - /* arg! must unbusy our page and fail or sleep. */
> +
> + /*
> + * arg! must unbusy our page and fail or sleep.
> + */
> if (uobjpage != PGO_DONTCARE) {
> uvm_lock_pageq();
> uvm_pageactivate(uobjpage);
> @@ -1378,7 +1402,10 @@ uvm_fault_lower(struct uvm_faultinfo *uf
> return ERESTART;
> }
>
> - /* fill in the data */
> + /*
> + * fill in the data
> + */
> +
> if (uobjpage != PGO_DONTCARE) {
> counters_inc(uvmexp_counters, flt_prcopy);
> /* copy page [pg now dirty] */
> @@ -1559,9 +1586,12 @@ uvm_fault_unwire_locked(vm_map_t map, va
> * the PAs from the pmap. we also lock out the page daemon so that
> * we can call uvm_pageunwire.
> */
> +
> uvm_lock_pageq();
>
> - /* find the beginning map entry for the region. */
> + /*
> + * find the beginning map entry for the region.
> + */
> KASSERT(start >= vm_map_min(map) && end <= vm_map_max(map));
> if (uvm_map_lookup_entry(map, start, &entry) == FALSE)
> panic("uvm_fault_unwire_locked: address not in map");
> @@ -1570,7 +1600,9 @@ uvm_fault_unwire_locked(vm_map_t map, va
> if (pmap_extract(pmap, va, &pa) == FALSE)
> continue;
>
> - /* find the map entry for the current address. */
> + /*
> + * find the map entry for the current address.
> + */
> KASSERT(va >= entry->start);
> while (va >= entry->end) {
> next = RBT_NEXT(uvm_map_addr, entry);
> @@ -1578,7 +1610,9 @@ uvm_fault_unwire_locked(vm_map_t map, va
> entry = next;
> }
>
> - /* if the entry is no longer wired, tell the pmap. */
> + /*
> + * if the entry is no longer wired, tell the pmap.
> + */
> if (VM_MAPENT_ISWIRED(entry) == 0)
> pmap_unwire(pmap, va);
>
> @@ -1646,7 +1680,10 @@ uvmfault_lookup(struct uvm_faultinfo *uf
> {
> vm_map_t tmpmap;
>
> - /* init ufi values for lookup. */
> + /*
> + * init ufi values for lookup.
> + */
> +
> ufi->map = ufi->orig_map;
> ufi->size = ufi->orig_size;
>
> @@ -1688,11 +1725,15 @@ uvmfault_lookup(struct uvm_faultinfo *uf
> continue;
> }
>
> - /* got it! */
> + /*
> + * got it!
> + */
> +
> ufi->mapv = ufi->map->timestamp;
> return(TRUE);
>
> - }
> + } /* while loop */
> +
> /*NOTREACHED*/
> }
>
> Index: uvm/uvm_init.c
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_init.c,v
> retrieving revision 1.41
> diff -u -p -r1.41 uvm_init.c
> --- uvm/uvm_init.c 28 Dec 2020 14:01:23 -0000 1.41
> +++ uvm/uvm_init.c 17 Mar 2021 12:03:12 -0000
> @@ -69,41 +69,41 @@ vaddr_t vm_min_kernel_address;
> /*
> * uvm_init: init the VM system. called from kern/init_main.c.
> */
> +
> void
> uvm_init(void)
> {
> vaddr_t kvm_start, kvm_end;
>
> - /* step 0: ensure that the hardware set the page size */
> + /*
> + * Ensure that the hardware set the page size.
> + */
> if (uvmexp.pagesize == 0) {
> panic("uvm_init: page size not set");
> }
> -
> - /* step 1: set up stats. */
> averunnable.fscale = FSCALE;
>
> /*
> - * step 2: init the page sub-system. this includes allocating the
> - * vm_page structures, and setting up all the page queues (and
> - * locks). available memory will be put in the "free" queue.
> - * kvm_start and kvm_end will be set to the area of kernel virtual
> - * memory which is available for general use.
> + * Init the page sub-system. This includes allocating the vm_page
> + * structures, and setting up all the page queues (and locks).
> + * Available memory will be put in the "free" queue, kvm_start and
> + * kvm_end will be set to the area of kernel virtual memory which
> + * is available for general use.
> */
> uvm_page_init(&kvm_start, &kvm_end);
>
> /*
> - * step 3: init the map sub-system. allocates the static pool of
> - * vm_map_entry structures that are used for "special" kernel maps
> - * (e.g. kernel_map, kmem_map, etc...).
> + * Init the map sub-system.
> + *
> + * Allocates the static pool of vm_map_entry structures that are
> + * used for "special" kernel maps (e.g. kernel_map, kmem_map, etc...).
> */
> uvm_map_init();
>
> /*
> - * step 4: setup the kernel's virtual memory data structures. this
> - * includes setting up the kernel_map/kernel_object and the kmem_map/
> - * kmem_object.
> + * Setup the kernel's virtual memory data structures. This includes
> + * setting up the kernel_map/kernel_object.
> */
> -
> uvm_km_init(vm_min_kernel_address, kvm_start, kvm_end);
>
> /*
> @@ -112,7 +112,7 @@ uvm_init(void)
> uvmfault_init();
>
> /*
> - * step 5: init the pmap module. the pmap module is free to allocate
> + * Init the pmap module. The pmap module is free to allocate
> * memory for its private use (e.g. pvlists).
> */
> pmap_init();
> @@ -123,8 +123,8 @@ uvm_init(void)
> uvm_km_page_init();
>
> /*
> - * step 7: init the kernel memory allocator. after this call the
> - * kernel memory allocator (malloc) can be used.
> + * Make kernel memory allocators ready for use.
> + * After this call the pool/kmem memory allocators can be used.
> */
I think this is misleading. kmeminit() only concerns malloc.
> kmeminit();
>
> @@ -134,7 +134,7 @@ uvm_init(void)
> dma_alloc_init();
>
> /*
> - * step 8: init all pagers and the pager_map.
> + * Init all pagers and the pager_map.
> */
> uvm_pager_init();
>
> @@ -172,7 +172,7 @@ uvm_init(void)
> panic("uvm_init: cannot reserve dead beef @0x%x", DEADBEEF1);
> #endif
> /*
> - * init anonymous memory systems
> + * Init anonymous memory systems.
> */
> uvm_anon_init();
>
> Index: uvm/uvm_io.c
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_io.c,v
> retrieving revision 1.26
> diff -u -p -r1.26 uvm_io.c
> --- uvm/uvm_io.c 9 Jan 2016 11:34:27 -0000 1.26
> +++ uvm/uvm_io.c 17 Mar 2021 12:04:19 -0000
> @@ -87,9 +87,16 @@ uvm_io(vm_map_t map, struct uio *uio, in
> if (flags & UVM_IO_FIXPROT)
> extractflags |= UVM_EXTRACT_FIXPROT;
>
> - /* step 1: main loop... while we've got data to move */
> + /*
> + * step 1: main loop... while we've got data to move
> + */
> +
> for (/*null*/; togo > 0 ; pageoffset = 0) {
> - /* step 2: extract mappings from the map into kernel_map */
> +
> + /*
> + * step 2: extract mappings from the map into kernel_map
> + */
> +
> error = uvm_map_extract(map, baseva, chunksz, &kva,
> extractflags);
> if (error) {
> @@ -105,7 +112,10 @@ uvm_io(vm_map_t map, struct uio *uio, in
> break;
> }
>
> - /* step 3: move a chunk of data */
> + /*
> + * step 3: move a chunk of data
> + */
> +
> sz = chunksz - pageoffset;
> if (sz > togo)
> sz = togo;
> @@ -113,7 +123,11 @@ uvm_io(vm_map_t map, struct uio *uio, in
> togo -= sz;
> baseva += chunksz;
>
> - /* step 4: unmap the area of kernel memory */
> +
> + /*
> + * step 4: unmap the area of kernel memory
> + */
> +
> vm_map_lock(kernel_map);
> TAILQ_INIT(&dead_entries);
> uvm_unmap_remove(kernel_map, kva, kva+chunksz,
> @@ -121,10 +135,6 @@ uvm_io(vm_map_t map, struct uio *uio, in
> vm_map_unlock(kernel_map);
> uvm_unmap_detach(&dead_entries, AMAP_REFALL);
>
> - /*
> - * We defer checking the error return from uiomove until
> - * here so that we won't leak memory.
> - */
> if (error)
> break;
> }
> Index: uvm/uvm_km.c
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_km.c,v
> retrieving revision 1.141
> diff -u -p -r1.141 uvm_km.c
> --- uvm/uvm_km.c 12 Mar 2021 14:15:49 -0000 1.141
> +++ uvm/uvm_km.c 17 Mar 2021 09:28:07 -0000
> @@ -223,7 +223,10 @@ uvm_km_suballoc(struct vm_map *map, vadd
> uvm_map_setup(submap, vm_map_pmap(map), *min, *max, flags);
> }
>
> - /* now let uvm_map_submap plug in it... */
> + /*
> + * now let uvm_map_submap plug in it...
> + */
> +
> if (uvm_map_submap(map, *min, *max, submap) != 0)
> panic("uvm_km_suballoc: submap allocation failed");
>
> @@ -541,7 +544,9 @@ uvm_km_valloc_align(struct vm_map *map,
> size = round_page(size);
> kva = vm_map_min(map); /* hint */
>
> - /* allocate some virtual space, demand filled by kernel_object. */
> + /*
> + * allocate some virtual space. will be demand filled by kernel_object.
> + */
>
> if (__predict_false(uvm_map(map, &kva, size, uvm.kernel_object,
> UVM_UNKNOWN_OFFSET, align,
>
>