On Mon, Apr 25, 2022 at 02:52:08PM +0000, Visa Hankala wrote:
> 
> The patch uses membar_sync(), and not membar_enter(), after the loop
> in refcnt_finalize() because subsequent memory operations should hinge
> on the load of r_refs.
> 
> membar_enter() is usable when the reference point is a store.
> 
> > The other issue I have with the diff is that it documentations the
> > memory ordering in terms of acquire and release which is not what we
> > do in other places such as the membar_enter(9) man page.  Maybe this
> > should explicitly call out the memory ordering like what the Linux
> > comment does.
> 
> I have updated the documentation, though I am not sure if the outcome
> is an improvement.

OK bluhm@

> Index: share/man/man9/refcnt_init.9
> ===================================================================
> RCS file: src/share/man/man9/refcnt_init.9,v
> retrieving revision 1.2
> diff -u -p -r1.2 refcnt_init.9
> --- share/man/man9/refcnt_init.9      16 Mar 2022 14:13:01 -0000      1.2
> +++ share/man/man9/refcnt_init.9      25 Apr 2022 14:34:05 -0000
> @@ -74,6 +74,17 @@ There may only be one caller to
>  per refcnt
>  .Fa r .
>  .Pp
> +.Fn refcnt_rele ,
> +.Fn refcnt_rele_wake
> +and
> +.Fn refcnt_finalize
> +order prior memory loads and stores before the release of the reference.
> +The functions enforce control dependency so that after the final reference
> +has been released, subsequent loads and stores happen after the release.
> +These ensure that concurrent accesses cease before the object's destructor
> +runs and that the destructor sees all updates done during the lifetime
> +of the object.
> +.Pp
>  .Fn refcnt_shared
>  tests if the object has multiple references.
>  .Pp
> Index: sys/kern/kern_synch.c
> ===================================================================
> RCS file: src/sys/kern/kern_synch.c,v
> retrieving revision 1.185
> diff -u -p -r1.185 kern_synch.c
> --- sys/kern/kern_synch.c     18 Mar 2022 15:32:06 -0000      1.185
> +++ sys/kern/kern_synch.c     25 Apr 2022 14:34:05 -0000
> @@ -822,9 +822,14 @@ refcnt_rele(struct refcnt *r)
>  {
>       u_int refs;
>  
> +     membar_exit_before_atomic();
>       refs = atomic_dec_int_nv(&r->r_refs);
>       KASSERT(refs != ~0);
> -     return (refs == 0);
> +     if (refs == 0) {
> +             membar_enter_after_atomic();
> +             return (1);
> +     }
> +     return (0);
>  }
>  
>  void
> @@ -840,6 +845,7 @@ refcnt_finalize(struct refcnt *r, const 
>       struct sleep_state sls;
>       u_int refs;
>  
> +     membar_exit_before_atomic();
>       refs = atomic_dec_int_nv(&r->r_refs);
>       KASSERT(refs != ~0);
>       while (refs) {
> @@ -847,6 +853,8 @@ refcnt_finalize(struct refcnt *r, const 
>               refs = atomic_load_int(&r->r_refs);
>               sleep_finish(&sls, refs);
>       }
> +     /* Order subsequent loads and stores after refs == 0 load. */
> +     membar_sync();
>  }
>  
>  int

Reply via email to