On Fri, Oct 30, 2020 at 08:46:20PM +0100, Martin Pieuchot wrote:
> On 23/10/20(Fri) 10:31, Martin Pieuchot wrote:
> > More refactoring.  This time let's introduce a helper to manipulate
> > references.  The goal is to reduce the upcoming diff adding locking.
> > 
> > This is extracted from a bigger diff from guenther@ as well as some
> > bits from NetBSD.
> 
> Now with the correct diff, ok?

This looks good to me (and survived a couple of full builds on amd64),
ok jmatthew@



> 
> Index: uvm/uvm_amap.c
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_amap.c,v
> retrieving revision 1.85
> diff -u -p -r1.85 uvm_amap.c
> --- uvm/uvm_amap.c    12 Oct 2020 08:44:45 -0000      1.85
> +++ uvm/uvm_amap.c    23 Oct 2020 08:23:59 -0000
> @@ -68,7 +68,23 @@ static inline void amap_list_remove(stru
>  
>  struct vm_amap_chunk *amap_chunk_get(struct vm_amap *, int, int, int);
>  void amap_chunk_free(struct vm_amap *, struct vm_amap_chunk *);
> -void amap_wiperange_chunk(struct vm_amap *, struct vm_amap_chunk *, int, 
> int);
> +
> +/*
> + * if we enable PPREF, then we have a couple of extra functions that
> + * we need to prototype here...
> + */
> +
> +#ifdef UVM_AMAP_PPREF
> +
> +#define PPREF_NONE ((int *) -1)      /* not using ppref */
> +
> +void amap_pp_adjref(struct vm_amap *, int, vsize_t, int);
> +void amap_pp_establish(struct vm_amap *);
> +void amap_wiperange_chunk(struct vm_amap *, struct vm_amap_chunk *, int,
> +         int);
> +void amap_wiperange(struct vm_amap *, int, int);
> +
> +#endif       /* UVM_AMAP_PPREF */
>  
>  static inline void
>  amap_list_insert(struct vm_amap *amap)
> @@ -1153,6 +1169,32 @@ amap_unadd(struct vm_aref *aref, vaddr_t
>  }
>  
>  /*
> + * amap_adjref_anons: adjust the reference count(s) on amap and its anons.
> + */
> +static void
> +amap_adjref_anons(struct vm_amap *amap, vaddr_t offset, vsize_t len,
> +    int refv, boolean_t all)
> +{
> +#ifdef UVM_AMAP_PPREF
> +     if (amap->am_ppref == NULL && !all && len != amap->am_nslot) {
> +             amap_pp_establish(amap);
> +     }
> +#endif
> +
> +     amap->am_ref += refv;
> +
> +#ifdef UVM_AMAP_PPREF
> +     if (amap->am_ppref && amap->am_ppref != PPREF_NONE) {
> +             if (all) {
> +                     amap_pp_adjref(amap, 0, amap->am_nslot, refv);
> +             } else {
> +                     amap_pp_adjref(amap, offset, len, refv);
> +             }
> +     }
> +#endif
> +}
> +
> +/*
>   * amap_ref: gain a reference to an amap
>   *
>   * => "offset" and "len" are in units of pages
> @@ -1162,51 +1204,36 @@ void
>  amap_ref(struct vm_amap *amap, vaddr_t offset, vsize_t len, int flags)
>  {
>  
> -     amap->am_ref++;
>       if (flags & AMAP_SHARED)
>               amap->am_flags |= AMAP_SHARED;
> -#ifdef UVM_AMAP_PPREF
> -     if (amap->am_ppref == NULL && (flags & AMAP_REFALL) == 0 &&
> -         len != amap->am_nslot)
> -             amap_pp_establish(amap);
> -     if (amap->am_ppref && amap->am_ppref != PPREF_NONE) {
> -             if (flags & AMAP_REFALL)
> -                     amap_pp_adjref(amap, 0, amap->am_nslot, 1);
> -             else
> -                     amap_pp_adjref(amap, offset, len, 1);
> -     }
> -#endif
> +     amap_adjref_anons(amap, offset, len, 1, (flags & AMAP_REFALL) != 0);
>  }
>  
>  /*
>   * amap_unref: remove a reference to an amap
>   *
> - * => caller must remove all pmap-level references to this amap before
> - *   dropping the reference
> - * => called from uvm_unmap_detach [only]  ... note that entry is no
> - *   longer part of a map
> + * => All pmap-level references to this amap must be already removed.
> + * => Called from uvm_unmap_detach(); entry is already removed from the map.
>   */
>  void
>  amap_unref(struct vm_amap *amap, vaddr_t offset, vsize_t len, boolean_t all)
>  {
> +     KASSERT(amap->am_ref > 0);
>  
> -     /* if we are the last reference, free the amap and return. */
> -     if (amap->am_ref-- == 1) {
> -             amap_wipeout(amap);     /* drops final ref and frees */
> +     if (amap->am_ref == 1) {
> +             /*
> +              * If the last reference - wipeout and destroy the amap.
> +              */
> +             amap->am_ref--;
> +             amap_wipeout(amap);
>               return;
>       }
>  
> -     /* otherwise just drop the reference count(s) */
> -     if (amap->am_ref == 1 && (amap->am_flags & AMAP_SHARED) != 0)
> -             amap->am_flags &= ~AMAP_SHARED; /* clear shared flag */
> -#ifdef UVM_AMAP_PPREF
> -     if (amap->am_ppref == NULL && all == 0 && len != amap->am_nslot)
> -             amap_pp_establish(amap);
> -     if (amap->am_ppref && amap->am_ppref != PPREF_NONE) {
> -             if (all)
> -                     amap_pp_adjref(amap, 0, amap->am_nslot, -1);
> -             else
> -                     amap_pp_adjref(amap, offset, len, -1);
> +     /*
> +      * Otherwise, drop the reference count(s) on anons.
> +      */
> +     if (amap->am_ref == 2 && (amap->am_flags & AMAP_SHARED) != 0) {
> +             amap->am_flags &= ~AMAP_SHARED;
>       }
> -#endif
> +     amap_adjref_anons(amap, offset, len, -1, all);
>  }
> Index: uvm/uvm_amap.h
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_amap.h,v
> retrieving revision 1.31
> diff -u -p -r1.31 uvm_amap.h
> --- uvm/uvm_amap.h    15 May 2019 06:12:19 -0000      1.31
> +++ uvm/uvm_amap.h    23 Oct 2020 08:19:43 -0000
> @@ -261,23 +261,6 @@ struct vm_amap {
>  #define amap_flags(AMAP)     ((AMAP)->am_flags)
>  #define amap_refs(AMAP)              ((AMAP)->am_ref)
>  
> -/*
> - * if we enable PPREF, then we have a couple of extra functions that
> - * we need to prototype here...
> - */
> -
> -#ifdef UVM_AMAP_PPREF
> -
> -#define PPREF_NONE ((int *) -1)      /* not using ppref */
> -
> -                                     /* adjust references */
> -void         amap_pp_adjref(struct vm_amap *, int, vsize_t, int);
> -                                     /* establish ppref */
> -void         amap_pp_establish(struct vm_amap *);
> -                                     /* wipe part of an amap */
> -void         amap_wiperange(struct vm_amap *, int, int);
> -#endif       /* UVM_AMAP_PPREF */
> -
>  #endif /* _KERNEL */
>  
>  #endif /* _UVM_UVM_AMAP_H_ */
> 

Reply via email to