Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 16 Sep 2015 13:54:47 -0700
From:      Randall Stewart <rrs@netflix.com>
To:        Hans Petter Selasky <hselasky@freebsd.org>
Cc:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   Re: svn commit: r287780 - in head: share/man/man9 sys/kern sys/sys
Message-ID:  <C6E2C380-AF00-4CAD-BBD4-8F73BCEB89A1@netflix.com>
In-Reply-To: <201509141052.t8EAqRWf008293@repo.freebsd.org>
References:  <201509141052.t8EAqRWf008293@repo.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
Hans:

By outside prompting, I have finally had a chance to look at this:

What it appears you do here is:

a) stop the callout, not paying attention to if it stopped or not.
b) Then get the callout systems lock and check if your callout is up and =
running, storing that in your
     retval. Where 1 is it was running, and 0 is no it was not running.
 c) Assuming that your callout is running.
   1) assert the user has the lock (if its a mtx associated lock), which =
means the callout is blocked on you finishing this.
   2) change the nature of the callout so that it will return-unlocked =
(no matter what the caller thought he set in his callout).
   3) Start a timeout using this same callout that calls the function =
(async drain function) that the user supplied *instead* of
       the original callout.

Now this is *not* how I would have done it and I question c.2 =
especially. I don=92t think
you should be changing the nature of the callout and its lock. =20

Overall I really doubt this will work well since the callout that you =
start will call to the user
function that says =93I am done with the callout memory.. which is =
usually what you want this async-drain for=94 but
using the very memory that you want to free for the callout.

I wonder how tested this code is? =20

I would think one would be better off having a way to set a callback if =
you are trying to stop and drain-async
that the actual callout code itself calls to say =93I am done=94.. not =
this interesting recursive use
of the callout itself.

R
On Sep 14, 2015, at 3:52 AM, Hans Petter Selasky <hselasky@freebsd.org> =
wrote:

> Author: hselasky
> Date: Mon Sep 14 10:52:26 2015
> New Revision: 287780
> URL: https://svnweb.freebsd.org/changeset/base/287780
>=20
> Log:
>  Implement callout_drain_async(), inspired by the projects/hps_head
>  branch.
>=20
>  This function is used to drain a callout via a callback instead of
>  blocking the caller until the drain is complete. Refer to the
>  callout_drain_async() manual page for a detailed description.
>=20
>  Limitation: If a lock is used with the callout, the callout can only
>  be drained asynchronously one time unless the callout_init_mtx()
>  function is called again. This limitation is not present in
>  projects/hps_head and will require more invasive changes to the
>  timeout code, which was not in the scope of this patch.
>=20
>  Differential Revision:	https://reviews.freebsd.org/D3521
>  Reviewed by:		wblock
>  MFC after:		1 month
>=20
> Modified:
>  head/share/man/man9/Makefile
>  head/share/man/man9/timeout.9
>  head/sys/kern/kern_timeout.c
>  head/sys/sys/_callout.h
>  head/sys/sys/callout.h
>=20
> Modified: head/share/man/man9/Makefile
> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
> --- head/share/man/man9/Makefile	Mon Sep 14 10:28:47 2015	=
(r287779)
> +++ head/share/man/man9/Makefile	Mon Sep 14 10:52:26 2015	=
(r287780)
> @@ -1641,6 +1641,7 @@ MLINKS+=3Dtimeout.9 callout.9 \
> 	timeout.9 callout_active.9 \
> 	timeout.9 callout_deactivate.9 \
> 	timeout.9 callout_drain.9 \
> +	timeout.9 callout_drain_async.9 \
> 	timeout.9 callout_handle_init.9 \
> 	timeout.9 callout_init.9 \
> 	timeout.9 callout_init_mtx.9 \
>=20
> Modified: head/share/man/man9/timeout.9
> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
> --- head/share/man/man9/timeout.9	Mon Sep 14 10:28:47 2015	=
(r287779)
> +++ head/share/man/man9/timeout.9	Mon Sep 14 10:52:26 2015	=
(r287780)
> @@ -36,6 +36,7 @@
> .Nm callout_active ,
> .Nm callout_deactivate ,
> .Nm callout_drain ,
> +.Nm callout_drain_async ,
> .Nm callout_handle_init ,
> .Nm callout_init ,
> .Nm callout_init_mtx ,
> @@ -70,6 +71,8 @@ typedef void timeout_t (void *);
> .Fn callout_deactivate "struct callout *c"
> .Ft int
> .Fn callout_drain "struct callout *c"
> +.Ft int
> +.Fn callout_drain_async "struct callout *c" "callout_func_t *fn" =
"void *arg"
> .Ft void
> .Fn callout_handle_init "struct callout_handle *handle"
> .Bd -literal
> @@ -264,6 +267,24 @@ fully stopped before
> .Fn callout_drain
> returns.
> .Pp
> +The function
> +.Fn callout_drain_async
> +is non-blocking and works the same as the
> +.Fn callout_stop
> +function.
> +When this function returns non-zero, do not call it again until the =
callback function given by
> +.Fa fn
> +has been called with argument
> +.Fa arg .
> +Only one of
> +.Fn callout_drain
> +or
> +.Fn callout_drain_async
> +should be called at a time to drain a callout.
> +If this function returns zero, it is safe to free the callout =
structure pointed to by the
> +.Fa c
> +argument immediately.
> +.Pp
> The
> .Fn callout_reset
> and
>=20
> Modified: head/sys/kern/kern_timeout.c
> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
> --- head/sys/kern/kern_timeout.c	Mon Sep 14 10:28:47 2015	=
(r287779)
> +++ head/sys/kern/kern_timeout.c	Mon Sep 14 10:52:26 2015	=
(r287780)
> @@ -1145,6 +1145,45 @@ callout_schedule(struct callout *c, int=20
> }
>=20
> int
> +callout_drain_async(struct callout *c, callout_func_t *func, void =
*arg)
> +{
> +	struct callout_cpu *cc;
> +	struct lock_class *class;
> +	int retval;
> +	int direct;
> +
> +	/* stop callout */
> +	callout_stop(c);
> +
> +	/* check if callback is being called */
> +	cc =3D callout_lock(c);
> +	if (c->c_iflags & CALLOUT_DIRECT) {
> +		direct =3D 1;
> +	} else {
> +		direct =3D 0;
> +	}
> +	retval =3D (cc_exec_curr(cc, direct) =3D=3D c);
> +
> +	/* drop locks, if any */
> +	if (retval && c->c_lock !=3D NULL &&
> +	    c->c_lock !=3D &Giant.lock_object) {
> +		/* ensure we are properly locked */
> +		class =3D LOCK_CLASS(c->c_lock);
> +		class->lc_assert(c->c_lock, LA_XLOCKED);
> +		/* the final callback should not be called locked */
> +		c->c_lock =3D NULL;
> +		c->c_iflags |=3D CALLOUT_RETURNUNLOCKED;
> +	}
> +	CC_UNLOCK(cc);
> +
> +	/* check if we should queue final callback */
> +	if (retval)
> +		callout_reset(c, 1, func, arg);
> +
> +	return (retval);
> +}
> +
> +int
> _callout_stop_safe(struct callout *c, int safe)
> {
> 	struct callout_cpu *cc, *old_cc;
>=20
> Modified: head/sys/sys/_callout.h
> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
> --- head/sys/sys/_callout.h	Mon Sep 14 10:28:47 2015	=
(r287779)
> +++ head/sys/sys/_callout.h	Mon Sep 14 10:52:26 2015	=
(r287780)
> @@ -46,6 +46,8 @@ LIST_HEAD(callout_list, callout);
> SLIST_HEAD(callout_slist, callout);
> TAILQ_HEAD(callout_tailq, callout);
>=20
> +typedef void callout_func_t(void *);
> +
> struct callout {
> 	union {
> 		LIST_ENTRY(callout) le;
>=20
> Modified: head/sys/sys/callout.h
> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
> --- head/sys/sys/callout.h	Mon Sep 14 10:28:47 2015	=
(r287779)
> +++ head/sys/sys/callout.h	Mon Sep 14 10:52:26 2015	=
(r287780)
> @@ -82,6 +82,7 @@ struct callout_handle {
> #define	callout_active(c)	((c)->c_flags & CALLOUT_ACTIVE)
> #define	callout_deactivate(c)	((c)->c_flags &=3D =
~CALLOUT_ACTIVE)
> #define	callout_drain(c)	_callout_stop_safe(c, 1)
> +int	callout_drain_async(struct callout *, callout_func_t *, void *);
> void	callout_init(struct callout *, int);
> void	_callout_init_lock(struct callout *, struct lock_object *, int);
> #define	callout_init_mtx(c, mtx, flags)					=
\
>=20

--------
Randall Stewart
rrs@netflix.com
803-317-4952








Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?C6E2C380-AF00-4CAD-BBD4-8F73BCEB89A1>