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