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)
>  {

Reply via email to