On Thu, Mar 10, 2022 at 02:03:26PM +0000, Visa Hankala wrote:
> My understanding is that OpenBSD's atomic_* instructions are relaxed
> in terms of memory order. To accomplish a specific form of semantics,
> the user adds the appropriate memory barrier instruction. Well, this
> is the plan at least, I think.
I also think that.
> Below is a patch that shows how to accomplish release semantics with
> the file and refcnt APIs. (The added memory barriers ensure that the
> CPU completes its loads and stores to the object before dropping the
> reference. Another CPU might delete the object immediately after.
> The barrier might not be strictly necessary with refcnt_finalize(),
> though.)
OK bluhm@
> Index: kern/kern_synch.c
> ===================================================================
> RCS file: src/sys/kern/kern_synch.c,v
> retrieving revision 1.182
> diff -u -p -r1.182 kern_synch.c
> --- kern/kern_synch.c 19 Feb 2022 23:56:18 -0000 1.182
> +++ kern/kern_synch.c 10 Mar 2022 13:37:50 -0000
> @@ -825,6 +825,7 @@ refcnt_rele(struct refcnt *r)
> {
> u_int refcnt;
>
> + membar_exit_before_atomic();
> refcnt = atomic_dec_int_nv(&r->refs);
> KASSERT(refcnt != ~0);
>
> @@ -844,6 +845,7 @@ refcnt_finalize(struct refcnt *r, const
> struct sleep_state sls;
> u_int refcnt;
>
> + membar_exit_before_atomic();
> refcnt = atomic_dec_int_nv(&r->refs);
> while (refcnt) {
> sleep_setup(&sls, r, PWAIT, wmesg, 0);
> Index: sys/file.h
> ===================================================================
> RCS file: src/sys/sys/file.h,v
> retrieving revision 1.65
> diff -u -p -r1.65 file.h
> --- sys/file.h 20 Jan 2022 03:43:31 -0000 1.65
> +++ sys/file.h 10 Mar 2022 13:37:50 -0000
> @@ -36,6 +36,7 @@
> #include <sys/fcntl.h>
>
> #else /* _KERNEL */
> +#include <sys/atomic.h>
> #include <sys/queue.h>
> #include <sys/mutex.h>
> #endif /* _KERNEL */
> @@ -113,13 +114,21 @@ struct file {
> atomic_inc_int(&(fp)->f_count); \
> } while (0)
>
> -#define FRELE(fp,p) \
> - (atomic_dec_int_nv(&fp->f_count) == 0 ? fdrop(fp, p) : 0)
> -
> #define FDUP_MAX_COUNT (UINT_MAX - 2 * MAXCPUS)
>
> int fdrop(struct file *, struct proc *);
>
> +static inline int
> +FRELE(struct file *fp, struct proc *p)
> +{
> + int error = 0;
> +
> + membar_exit_before_atomic();
> + if (atomic_dec_int_nv(&fp->f_count) == 0)
> + error = fdrop(fp, p);
> + return (error);
> +}
> +
> static inline off_t
> foffset(struct file *fp)
> {