svn commit: r304167 - in projects/hps_head: share/man/man9 sys/dev/nand sys/dev/oce sys/kern sys/net sys/netgraph sys/netinet sys/netinet6 sys/netpfil/pf sys/sys sys/tests/callout_test

Hans Petter Selasky hselasky at FreeBSD.org
Mon Aug 15 17:37:31 UTC 2016


Author: hselasky
Date: Mon Aug 15 17:37:28 2016
New Revision: 304167
URL: https://svnweb.freebsd.org/changeset/base/304167

Log:
  Make all callout_xxx() functions use the same return value. Split the
  callout return value into two bits indicating either cancelled or
  draining/servicing state. This gets us a total of four callout states
  instead of three. This also will allow better diagnosis and debugging
  of callout related problems.
  
  Identify all callout clients in the kernel and make them use the
  correct CALLOUT_RET_XXX return value and test.
  
  Update the timeout(9) manual page to reflect these changes.

Modified:
  projects/hps_head/share/man/man9/timeout.9
  projects/hps_head/sys/dev/nand/nandsim_chip.c
  projects/hps_head/sys/dev/oce/oce_if.c
  projects/hps_head/sys/kern/kern_exit.c
  projects/hps_head/sys/kern/kern_timeout.c
  projects/hps_head/sys/kern/subr_taskqueue.c
  projects/hps_head/sys/net/if_llatbl.c
  projects/hps_head/sys/net/if_spppsubr.c
  projects/hps_head/sys/netgraph/ng_base.c
  projects/hps_head/sys/netinet/if_ether.c
  projects/hps_head/sys/netinet/in.c
  projects/hps_head/sys/netinet/tcp_timer.c
  projects/hps_head/sys/netinet6/in6.c
  projects/hps_head/sys/netinet6/nd6.c
  projects/hps_head/sys/netpfil/pf/if_pfsync.c
  projects/hps_head/sys/sys/callout.h
  projects/hps_head/sys/tests/callout_test/callout_test.c

Modified: projects/hps_head/share/man/man9/timeout.9
==============================================================================
--- projects/hps_head/share/man/man9/timeout.9	Mon Aug 15 17:11:05 2016	(r304166)
+++ projects/hps_head/share/man/man9/timeout.9	Mon Aug 15 17:37:28 2016	(r304167)
@@ -29,7 +29,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd July 27, 2016
+.Dd August 15, 2016
 .Dt TIMEOUT 9
 .Os
 .Sh NAME
@@ -323,18 +323,10 @@ The number of ticks in a second is defin
 and can vary from system to system.
 This function returns either
 .Dv CALLOUT_RET_STOPPED ,
-.Dv CALLOUT_RET_CANCELLED
-or
-.Dv CALLOUT_RET_DRAINING .
-If the callout was scheduled regardless of being serviced or not,
-.Dv CALLOUT_RET_CANCELLED
-is returned.
-If the callout was stopped and is still being serviced
+.Dv CALLOUT_RET_CANCELLED ,
 .Dv CALLOUT_RET_DRAINING
-is returned.
-If the callout was stopped and is no longer being serviced
-.Dv CALLOUT_RET_STOPPED
-is returned.
+or
+.Dv CALLOUT_RET_CANCELLED_AND_DRAINING .
 If a lock is associated with the callout given by the
 .Fa c
 argument and it is exclusivly locked when this function is called, this
@@ -594,18 +586,10 @@ This function can be called multiple tim
 This function however should not be called before the callout has been initialized.
 This function returns either
 .Dv CALLOUT_RET_STOPPED ,
-.Dv CALLOUT_RET_CANCELLED
-or
-.Dv CALLOUT_RET_DRAINING .
-If the callout was scheduled regardless of being serviced or not,
-.Dv CALLOUT_RET_CANCELLED
-is returned.
-If the callout was stopped and is still being serviced
+.Dv CALLOUT_RET_CANCELLED ,
 .Dv CALLOUT_RET_DRAINING
-is returned.
-If the callout was stopped and is no longer being serviced
-.Dv CALLOUT_RET_STOPPED
-is returned.
+or
+.Dv CALLOUT_RET_CANCELLED_AND_DRAINING .
 If a lock is associated with the callout given by the
 .Fa c
 argument and it is exclusivly locked when this function is called, the
@@ -631,22 +615,24 @@ argument.
 .Fn callout_async_drain "struct callout *c" "callout_func_t *drain"
 This function is non-blocking and works the same like the
 .Fn callout_stop
-function except if it returns
+function except if the
 .Dv CALLOUT_RET_DRAINING
-it means the callback function pointed to by the
+bit in the return value is non-zero,
+the callback function pointed to by the
 .Fa drain
 argument will be called back with the
 .Fa arg
 argument when all references to the callout pointed to by the
 .Fa c
 argument are gone.
-If this function returns
+If the
 .Dv CALLOUT_RET_DRAINING
-it should not be called again until the callback function has been called.
+bit is set in the return value this function should not be called
+again until the callback function has been called.
 Note that when stopping multiple callouts that use the same lock it is possible
-to get multiple return values of
+to get multiple return values where the
 .Dv CALLOUT_RET_DRAINING
-and multiple calls to the
+bit is set and multiple calls to the
 .Fa drain
 function, depending upon which CPU's the callouts are running on.
 The
@@ -659,9 +645,10 @@ or
 .Fn callout_async_drain
 functions are called while an asynchronous drain is pending,
 previously pending asynchronous drains might get cancelled.
-If this function returns a value different from
+If the
 .Dv CALLOUT_RET_DRAINING
-it is safe to free the callout structure pointed to by the
+bit is not set in the return value it is safe to free the callout
+structure pointed to by the
 .Fa c
 argument right away.
 .Pp
@@ -698,11 +685,19 @@ trying to read this time from the callou
 .Fn callout_reset
 call is racy.
 .Sh CALLOUT FUNCTION RETURN VALUES
-.Bl -tag -width ".Dv CALLOUT_RET_CANCELLED"
+.Bl -tag -width ".Dv CALLOUT_RET_CANCELLED_AND_DRAINING"
+.It CALLOUT_RET_CANCELLED_AND_DRAINING
+The callout was successfully stopped and needs to be drained.
+This return value is the result of binary OR-ing
+.Dv CALLOUT_RET_DRAINING
+and
+.Dv CALLOUT_RET_CANCELLED .
 .It CALLOUT_RET_DRAINING
 The callout cannot be stopped and needs to be drained.
+This return value is a single bit which can be bit-tested.
 .It CALLOUT_RET_CANCELLED
 The callout was successfully stopped.
+This return value is a single bit which can be bit-tested.
 .It CALLOUT_RET_STOPPED
 The callout was already stopped.
 .El
@@ -792,8 +787,9 @@ callout function is about to be called.
 For example:
 .Bd -literal -offset indent
 if (sc->sc_flags & SCFLG_CALLOUT_RUNNING) {
-	if (callout_stop(&sc->sc_callout) ==
-	    CALLOUT_RET_CANCELLED) {
+	int ret;
+	ret = callout_stop(&sc->sc_callout);
+	if (ret & CALLOUT_RET_CANCELLED) {
 		sc->sc_flags &= ~SCFLG_CALLOUT_RUNNING;
 		/* successfully stopped */
 	} else {

Modified: projects/hps_head/sys/dev/nand/nandsim_chip.c
==============================================================================
--- projects/hps_head/sys/dev/nand/nandsim_chip.c	Mon Aug 15 17:11:05 2016	(r304166)
+++ projects/hps_head/sys/dev/nand/nandsim_chip.c	Mon Aug 15 17:37:28 2016	(r304167)
@@ -406,8 +406,11 @@ nandsim_delay(struct nandsim_chip *chip,
 
 	chip->sm_state = NANDSIM_STATE_TIMEOUT;
 	tm = (timeout/10000) * (hz / 100);
-	if (callout_reset(&chip->ns_callout, tm, nandsim_callout_eh, ev))
+	if (callout_reset(&chip->ns_callout, tm, nandsim_callout_eh, ev) &
+	    CALLOUT_RET_CANCELLED) {
+		/* XXX we are leaking the old event */
 		return (-1);
+	}
 
 	delay.tv_sec = chip->read_delay / 1000000;
 	delay.tv_usec = chip->read_delay % 1000000;

Modified: projects/hps_head/sys/dev/oce/oce_if.c
==============================================================================
--- projects/hps_head/sys/dev/oce/oce_if.c	Mon Aug 15 17:11:05 2016	(r304166)
+++ projects/hps_head/sys/dev/oce/oce_if.c	Mon Aug 15 17:37:28 2016	(r304167)
@@ -343,7 +343,7 @@ oce_attach(device_t dev)
 
 	callout_init(&sc->timer, 1);
 	rc = callout_reset(&sc->timer, 2 * hz, oce_local_timer, sc);
-	if (rc == CALLOUT_RET_CANCELLED)
+	if (rc & CALLOUT_RET_CANCELLED)
 		goto stats_free;
 
 	return 0;

Modified: projects/hps_head/sys/kern/kern_exit.c
==============================================================================
--- projects/hps_head/sys/kern/kern_exit.c	Mon Aug 15 17:11:05 2016	(r304166)
+++ projects/hps_head/sys/kern/kern_exit.c	Mon Aug 15 17:37:28 2016	(r304167)
@@ -189,6 +189,7 @@ exit1(struct thread *td, int rval, int s
 {
 	struct proc *p, *nq, *q, *t;
 	struct thread *tdt;
+	int drain;
 
 	mtx_assert(&Giant, MA_NOTOWNED);
 	KASSERT(rval == 0 || signo == 0, ("exit1 rv %d sig %d", rval, signo));
@@ -343,16 +344,17 @@ exit1(struct thread *td, int rval, int s
 	 * Stop the real interval timer.  If the handler is currently
 	 * executing, prevent it from rearming itself and let it finish.
 	 */
-	if (timevalisset(&p->p_realtimer.it_value) &&
-	    callout_stop(&p->p_itcallout) == 0) {
+	if (timevalisset(&p->p_realtimer.it_value)) {
 		timevalclear(&p->p_realtimer.it_interval);
-		msleep(&p->p_itcallout, &p->p_mtx, PWAIT, "ritwait", 0);
-		KASSERT(!timevalisset(&p->p_realtimer.it_value),
-		    ("realtime timer is still armed"));
+		drain = callout_stop(&p->p_itcallout);
+	} else {
+		drain = 0;
 	}
-
 	PROC_UNLOCK(p);
 
+	if (drain & CALLOUT_RET_DRAINING)
+		callout_drain(&p->p_itcallout);
+
 	umtx_thread_exit(td);
 
 	/*

Modified: projects/hps_head/sys/kern/kern_timeout.c
==============================================================================
--- projects/hps_head/sys/kern/kern_timeout.c	Mon Aug 15 17:11:05 2016	(r304166)
+++ projects/hps_head/sys/kern/kern_timeout.c	Mon Aug 15 17:37:28 2016	(r304167)
@@ -1020,6 +1020,8 @@ callout_retvalstring(int retval)
 		return ("callout cannot be stopped and needs drain");
 	case CALLOUT_RET_CANCELLED:
 		return ("callout was successfully stopped");
+	case CALLOUT_RET_CANCELLED_AND_DRAINING:
+		return ("callout was successfully stopped while being serviced");
 	default:
 		return ("callout was already stopped");
 	}
@@ -1044,21 +1046,21 @@ callout_restart_async(struct callout *c,
 	 * completion:
 	 */
 	if (cc_exec_curr(cc, direct) == c) {
+
+		retval = CALLOUT_RET_DRAINING;
+
+		/* set drain function, if any */
+		if (drain_fn != NULL)
+			cc_exec_drain_fn(cc, direct) = drain_fn;
+
 		/*
 		 * Try to prevent the callback from running by setting
-		 * the "cc_cancel" variable to "true".
+		 * the "cc_exec_cancel()" variable to "true".
 		 */
-		if (drain_fn != NULL) {
-			/* set drain function, if any */
-			cc_exec_drain_fn(cc, direct) = drain_fn;
-			cc_exec_cancel(cc, direct) = true;
-			retval = CALLOUT_RET_DRAINING;
-		} else if (cc_exec_cancel(cc, direct) == false ||
+		if (cc_exec_cancel(cc, direct) == false ||
 		    cc_exec_restart(cc, direct) == true) {
 			cc_exec_cancel(cc, direct) = true;
-			retval = CALLOUT_RET_CANCELLED;
-		} else {
-			retval = CALLOUT_RET_DRAINING;
+			retval |= CALLOUT_RET_CANCELLED;
 		}
 
 		/*
@@ -1265,7 +1267,7 @@ callout_drain(struct callout *c)
 
 	retval = callout_async_drain(c, &callout_drain_function);
 
-	if (retval == CALLOUT_RET_DRAINING) {
+	if (retval & CALLOUT_RET_DRAINING) {
 		void *ident = &callout_drain_function;
 		struct callout_cpu *cc;
 		int direct;

Modified: projects/hps_head/sys/kern/subr_taskqueue.c
==============================================================================
--- projects/hps_head/sys/kern/subr_taskqueue.c	Mon Aug 15 17:11:05 2016	(r304166)
+++ projects/hps_head/sys/kern/subr_taskqueue.c	Mon Aug 15 17:37:28 2016	(r304167)
@@ -531,7 +531,7 @@ taskqueue_cancel_timeout(struct taskqueu
 	int error;
 
 	TQ_LOCK(queue);
-	pending = (callout_stop(&timeout_task->c) == CALLOUT_RET_CANCELLED) ? 1 : 0;
+	pending = (callout_stop(&timeout_task->c) & CALLOUT_RET_CANCELLED) ? 1 : 0;
 	error = taskqueue_cancel_locked(queue, &timeout_task->t, &pending1);
 	if ((timeout_task->f & DT_CALLOUT_ARMED) != 0) {
 		timeout_task->f &= ~DT_CALLOUT_ARMED;

Modified: projects/hps_head/sys/net/if_llatbl.c
==============================================================================
--- projects/hps_head/sys/net/if_llatbl.c	Mon Aug 15 17:11:05 2016	(r304166)
+++ projects/hps_head/sys/net/if_llatbl.c	Mon Aug 15 17:37:28 2016	(r304167)
@@ -515,7 +515,7 @@ lltable_free(struct lltable *llt)
 	IF_AFDATA_WUNLOCK(llt->llt_ifp);
 
 	LIST_FOREACH_SAFE(lle, &dchain, lle_chain, next) {
-		if (callout_stop(&lle->lle_timer) == CALLOUT_RET_CANCELLED)
+		if (callout_stop(&lle->lle_timer) & CALLOUT_RET_CANCELLED)
 			LLE_REMREF(lle);
 		llentry_free(lle);
 	}

Modified: projects/hps_head/sys/net/if_spppsubr.c
==============================================================================
--- projects/hps_head/sys/net/if_spppsubr.c	Mon Aug 15 17:11:05 2016	(r304166)
+++ projects/hps_head/sys/net/if_spppsubr.c	Mon Aug 15 17:37:28 2016	(r304167)
@@ -1060,15 +1060,13 @@ sppp_detach(struct ifnet *ifp)
 	KASSERT(mtx_initialized(&sp->mtx), ("sppp mutex is not initialized"));
 
 	/* Stop keepalive handler. */
- 	if (!callout_drain(&sp->keepalive_callout))
-		callout_stop(&sp->keepalive_callout);
+ 	callout_drain(&sp->keepalive_callout);
+
+	for (i = 0; i < IDX_COUNT; i++)
+		callout_drain(&sp->ch[i]);
+
+	callout_drain(&sp->pap_my_to_ch);
 
-	for (i = 0; i < IDX_COUNT; i++) {
-		if (!callout_drain(&sp->ch[i]))
-			callout_stop(&sp->ch[i]);
-	}
-	if (!callout_drain(&sp->pap_my_to_ch))
-		callout_stop(&sp->pap_my_to_ch);
 	mtx_destroy(&sp->pp_cpq.ifq_mtx);
 	mtx_destroy(&sp->pp_fastq.ifq_mtx);
 	mtx_destroy(&sp->mtx);

Modified: projects/hps_head/sys/netgraph/ng_base.c
==============================================================================
--- projects/hps_head/sys/netgraph/ng_base.c	Mon Aug 15 17:11:05 2016	(r304166)
+++ projects/hps_head/sys/netgraph/ng_base.c	Mon Aug 15 17:37:28 2016	(r304167)
@@ -3795,8 +3795,8 @@ ng_callout(struct callout *c, node_p nod
 	NGI_ARG1(item) = arg1;
 	NGI_ARG2(item) = arg2;
 	oitem = c->c_arg;
-	if (callout_reset(c, ticks, &ng_callout_trampoline, item) == 1 &&
-	    oitem != NULL)
+	if ((callout_reset(c, ticks, &ng_callout_trampoline, item) &
+	     CALLOUT_RET_CANCELLED) && oitem != NULL)
 		NG_FREE_ITEM(oitem);
 	return (0);
 }
@@ -3814,7 +3814,7 @@ ng_uncallout(struct callout *c, node_p n
 	rval = callout_stop(c);
 	item = c->c_arg;
 	/* Do an extra check */
-	if ((rval == CALLOUT_RET_CANCELLED) &&
+	if ((rval & CALLOUT_RET_CANCELLED) &&
 	    (c->c_func == &ng_callout_trampoline) &&
 	    (NGI_NODE(item) == node)) {
 		/*

Modified: projects/hps_head/sys/netinet/if_ether.c
==============================================================================
--- projects/hps_head/sys/netinet/if_ether.c	Mon Aug 15 17:11:05 2016	(r304166)
+++ projects/hps_head/sys/netinet/if_ether.c	Mon Aug 15 17:37:28 2016	(r304167)
@@ -537,7 +537,7 @@ arpresolve_full(struct ifnet *ifp, int i
 		la->la_expire = time_uptime;
 		canceled = callout_reset(&la->lle_timer, hz * V_arpt_down,
 		    arptimer, la);
-		if (canceled == CALLOUT_RET_CANCELLED)
+		if (canceled & CALLOUT_RET_CANCELLED)
 			LLE_REMREF(la);
 		la->la_asked++;
 		LLE_WUNLOCK(la);
@@ -1234,7 +1234,7 @@ arp_mark_lle_reachable(struct llentry *l
 			wtime = V_arpt_keep;
 		canceled = callout_reset(&la->lle_timer,
 		    hz * wtime, arptimer, la);
-		if (canceled == CALLOUT_RET_CANCELLED)
+		if (canceled & CALLOUT_RET_CANCELLED)
 			LLE_REMREF(la);
 	}
 	la->la_asked = 0;

Modified: projects/hps_head/sys/netinet/in.c
==============================================================================
--- projects/hps_head/sys/netinet/in.c	Mon Aug 15 17:11:05 2016	(r304166)
+++ projects/hps_head/sys/netinet/in.c	Mon Aug 15 17:37:28 2016	(r304167)
@@ -1137,7 +1137,7 @@ in_lltable_free_entry(struct lltable *ll
 	}
 
 	/* cancel timer */
-	if (callout_stop(&lle->lle_timer) == CALLOUT_RET_CANCELLED)
+	if (callout_stop(&lle->lle_timer) & CALLOUT_RET_CANCELLED)
 		LLE_REMREF(lle);
 
 	/* Drop hold queue */

Modified: projects/hps_head/sys/netinet/tcp_timer.c
==============================================================================
--- projects/hps_head/sys/netinet/tcp_timer.c	Mon Aug 15 17:11:05 2016	(r304166)
+++ projects/hps_head/sys/netinet/tcp_timer.c	Mon Aug 15 17:37:28 2016	(r304167)
@@ -366,8 +366,9 @@ tcp_timer_2msl(void *xtp)
 		tp = tcp_close(tp);             
 	} else {
 		if (ticks - tp->t_rcvtime <= TP_MAXIDLE(tp)) {
-			if (!callout_reset(&tp->t_timers->tt_2msl,
-			   TP_KEEPINTVL(tp), tcp_timer_2msl, tp)) {
+			if (!(callout_reset(&tp->t_timers->tt_2msl,
+			    TP_KEEPINTVL(tp), tcp_timer_2msl, tp) &
+			    CALLOUT_RET_CANCELLED)) {
 				tp->t_timers->tt_flags &= ~TT_2MSL_RST;
 			}
 		} else
@@ -452,12 +453,12 @@ tcp_timer_keep(void *xtp)
 				    tp->rcv_nxt, tp->snd_una - 1, 0);
 			free(t_template, M_TEMP);
 		}
-		if (!callout_reset(&tp->t_timers->tt_keep, TP_KEEPINTVL(tp),
-		    tcp_timer_keep, tp)) {
+		if (!(callout_reset(&tp->t_timers->tt_keep, TP_KEEPINTVL(tp),
+		    tcp_timer_keep, tp) & CALLOUT_RET_CANCELLED)) {
 			tp->t_timers->tt_flags &= ~TT_KEEP_RST;
 		}
-	} else if (!callout_reset(&tp->t_timers->tt_keep, TP_KEEPIDLE(tp),
-		    tcp_timer_keep, tp)) {
+	} else if (!(callout_reset(&tp->t_timers->tt_keep, TP_KEEPIDLE(tp),
+		   tcp_timer_keep, tp) & CALLOUT_RET_CANCELLED)) {
 			tp->t_timers->tt_flags &= ~TT_KEEP_RST;
 		}
 
@@ -877,7 +878,7 @@ tcp_timer_activate(struct tcpcb *tp, uin
 		}
 	if (delta == 0) {
 		if ((tp->t_timers->tt_flags & timer_type) &&
-		    (callout_stop(t_callout) > 0) &&
+		    (!(callout_stop(t_callout) & CALLOUT_RET_DRAINING)) &&
 		    (tp->t_timers->tt_flags & f_reset)) {
 			tp->t_timers->tt_flags &= ~(timer_type | f_reset);
 		}
@@ -887,7 +888,8 @@ tcp_timer_activate(struct tcpcb *tp, uin
 			callout_reset_on(t_callout, delta, f_callout, tp, cpu);
 		} else {
 			/* Reset already running callout on the same CPU. */
-			if (!callout_reset(t_callout, delta, f_callout, tp)) {
+			if (!(callout_reset(t_callout, delta, f_callout, tp) &
+			    CALLOUT_RET_CANCELLED)) {
 				/*
 				 * Callout not cancelled, consider it as not
 				 * properly restarted. */
@@ -969,7 +971,8 @@ tcp_timer_stop(struct tcpcb *tp, uint32_
 		}
 
 	if (tp->t_timers->tt_flags & timer_type) {
-		if (callout_async_drain(t_callout, tcp_timer_discard) == 0) {
+		if (callout_async_drain(t_callout, tcp_timer_discard) &
+		    CALLOUT_RET_DRAINING) {
 			/*
 			 * Can't stop the callout, defer tcpcb actual deletion
 			 * to the last one. We do this using the async drain

Modified: projects/hps_head/sys/netinet6/in6.c
==============================================================================
--- projects/hps_head/sys/netinet6/in6.c	Mon Aug 15 17:11:05 2016	(r304166)
+++ projects/hps_head/sys/netinet6/in6.c	Mon Aug 15 17:37:28 2016	(r304167)
@@ -2093,7 +2093,7 @@ in6_lltable_free_entry(struct lltable *l
 		lltable_unlink_entry(llt, lle);
 	}
 
-	if (callout_stop(&lle->lle_timer) == CALLOUT_RET_CANCELLED)
+	if (callout_stop(&lle->lle_timer) & CALLOUT_RET_CANCELLED)
 		LLE_REMREF(lle);
 
 	llentry_free(lle);

Modified: projects/hps_head/sys/netinet6/nd6.c
==============================================================================
--- projects/hps_head/sys/netinet6/nd6.c	Mon Aug 15 17:11:05 2016	(r304166)
+++ projects/hps_head/sys/netinet6/nd6.c	Mon Aug 15 17:37:28 2016	(r304167)
@@ -541,7 +541,7 @@ nd6_llinfo_settimer_locked(struct llentr
 			    nd6_llinfo_timer, ln);
 		}
 	}
-	if (canceled == CALLOUT_RET_CANCELLED)
+	if (canceled & CALLOUT_RET_CANCELLED)
 		LLE_REMREF(ln);
 }
 

Modified: projects/hps_head/sys/netpfil/pf/if_pfsync.c
==============================================================================
--- projects/hps_head/sys/netpfil/pf/if_pfsync.c	Mon Aug 15 17:11:05 2016	(r304166)
+++ projects/hps_head/sys/netpfil/pf/if_pfsync.c	Mon Aug 15 17:37:28 2016	(r304167)
@@ -353,7 +353,7 @@ pfsync_clone_destroy(struct ifnet *ifp)
 
 		TAILQ_REMOVE(&sc->sc_deferrals, pd, pd_entry);
 		sc->sc_deferred--;
-		if (callout_stop(&pd->pd_tmo) == CALLOUT_RET_CANCELLED) {
+		if (callout_stop(&pd->pd_tmo) & CALLOUT_RET_CANCELLED) {
 			pf_release_state(pd->pd_st);
 			m_freem(pd->pd_m);
 			free(pd, M_PFSYNC);
@@ -1776,7 +1776,7 @@ pfsync_undefer_state(struct pf_state *st
 
 	TAILQ_FOREACH(pd, &sc->sc_deferrals, pd_entry) {
 		 if (pd->pd_st == st) {
-			if (callout_stop(&pd->pd_tmo) == CALLOUT_RET_CANCELLED)
+			if (callout_stop(&pd->pd_tmo) & CALLOUT_RET_CANCELLED)
 				pfsync_undefer(pd, drop);
 			return;
 		}

Modified: projects/hps_head/sys/sys/callout.h
==============================================================================
--- projects/hps_head/sys/sys/callout.h	Mon Aug 15 17:11:05 2016	(r304166)
+++ projects/hps_head/sys/sys/callout.h	Mon Aug 15 17:37:28 2016	(r304167)
@@ -53,9 +53,10 @@
 #define	CALLOUT_GET_LC(x)	(((x) >> 16) & 7) /* get lock class */
 
 /* return values for all callout_xxx() functions */
-#define	CALLOUT_RET_DRAINING	0 /* callout cannot be stopped, need drain */
+#define	CALLOUT_RET_CANCELLED_AND_DRAINING (CALLOUT_RET_CANCELLED | CALLOUT_RET_DRAINING)
+#define	CALLOUT_RET_DRAINING	2 /* callout is being serviced */
 #define	CALLOUT_RET_CANCELLED	1 /* callout was successfully stopped */
-#define	CALLOUT_RET_STOPPED	-1 /* callout was already stopped */
+#define	CALLOUT_RET_STOPPED	0 /* callout was already stopped */
 
 #define	C_DIRECT_EXEC		0x0001 /* direct execution of callout */
 #define	C_PRELBITS		7

Modified: projects/hps_head/sys/tests/callout_test/callout_test.c
==============================================================================
--- projects/hps_head/sys/tests/callout_test/callout_test.c	Mon Aug 15 17:11:05 2016	(r304166)
+++ projects/hps_head/sys/tests/callout_test/callout_test.c	Mon Aug 15 17:37:28 2016	(r304167)
@@ -158,7 +158,7 @@ execute_the_co_test(struct callout_run *
 	/* OK everyone is waiting and we have the lock */
 	for (i = 0; i < rn->co_number_callouts; i++) {
 		ret = callout_async_drain(&rn->co_array[i], drainit);
-		if (ret) {
+		if (!(ret & CALLOUT_RET_DRAINING)) {
 			rn->cnt_one++;
 		} else {
 			rn->cnt_zero++;


More information about the svn-src-projects mailing list