Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 10 Aug 2016 14:31:32 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r303918 - in projects/hps_head: share/man/man9 sys/kern sys/sys
Message-ID:  <201608101431.u7AEVW88096940@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Wed Aug 10 14:31:32 2016
New Revision: 303918
URL: https://svnweb.freebsd.org/changeset/base/303918

Log:
  MFC r303425:
  Extract the calculation of the callout fire time into the new function
  callout_when(9).  See the man page update for the description of the
  intended use.
  
  Tested by:	pho
  Reviewed by:	jhb, bjk (man page updates)
  X-Differential revision:	https://reviews.freebsd.org/D7137

Modified:
  projects/hps_head/share/man/man9/Makefile
  projects/hps_head/share/man/man9/timeout.9
  projects/hps_head/sys/kern/kern_timeout.c
  projects/hps_head/sys/sys/callout.h

Modified: projects/hps_head/share/man/man9/Makefile
==============================================================================
--- projects/hps_head/share/man/man9/Makefile	Wed Aug 10 14:00:07 2016	(r303917)
+++ projects/hps_head/share/man/man9/Makefile	Wed Aug 10 14:31:32 2016	(r303918)
@@ -1766,6 +1766,7 @@ MLINKS+=timeout.9 callout.9 \
 	timeout.9 callout_schedule_sbt_curcpu.9 \
 	timeout.9 callout_schedule_sbt_on.9 \
 	timeout.9 callout_stop.9 \
+	timeout.9 callout_when.9 \
 	timeout.9 untimeout.9
 MLINKS+=ucred.9 cred_update_thread.9 \
 	ucred.9 crcopy.9 \

Modified: projects/hps_head/share/man/man9/timeout.9
==============================================================================
--- projects/hps_head/share/man/man9/timeout.9	Wed Aug 10 14:00:07 2016	(r303917)
+++ projects/hps_head/share/man/man9/timeout.9	Wed Aug 10 14:31:32 2016	(r303918)
@@ -29,7 +29,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd July 13, 2015
+.Dd July 27, 2016
 .Dt TIMEOUT 9
 .Os
 .Sh NAME
@@ -57,6 +57,7 @@
 .Nm callout_schedule_sbt_curcpu ,
 .Nm callout_schedule_sbt_on ,
 .Nm callout_stop ,
+.Nm callout_when ,
 .Nm timeout ,
 .Nm untimeout
 .Nd execute a function after a specified length of time
@@ -127,6 +128,8 @@ struct callout_handle handle = CALLOUT_H
 "sbintime_t pr" "int cpu" "int flags"
 .Ft int
 .Fn callout_stop "struct callout *c"
+.Ft void
+.Fn callout_when "sbintime_t sbt" "sbintime_t precision" "int flags" "sbintime_t *sbt_res" "sbintime_t *precision_res"
 .Ft struct callout_handle
 .Fn timeout "timeout_t *func" "void *arg" "int ticks"
 .Ft void
@@ -417,6 +420,26 @@ or this value is used as the length of t
 Smaller values
 .Pq which result in larger time intervals
 allow the callout subsystem to aggregate more events in one timer interrupt.
+.It Dv C_PRECALC
+The
+.Fa sbt
+argument specifies the absolute time at which the callout should be run,
+and the
+.Fa pr
+argument specifies the requested precision, which will not be
+adjusted during the scheduling process.
+The
+.Fa sbt
+and
+.Fa pr
+values should be calculated by an earlier call to
+.Fn callout_when
+which uses the user-supplied
+.Fa sbt ,
+.Fa pr ,
+and
+.Fa flags
+values.
 .It Dv C_HARDCLOCK
 Align the timeouts to
 .Fn hardclock
@@ -641,6 +664,39 @@ If this function returns a value differe
 it is safe to free the callout structure pointed to by the
 .Fa c
 argument right away.
+.Pp
+The
+.Fn callout_when
+function may be used to pre-calculate the absolute time at which the
+timeout should be run and the precision of the scheduled run time
+according to the required time
+.Fa sbt ,
+precision
+.Fa precision ,
+and additional adjustments requested by the
+.Fa flags
+argument.
+Flags accepted by the
+.Fn callout_when
+function are the same as flags for the
+.Fn callout_reset
+function.
+The resulting time is assigned to the variable pointed to by the
+.Fa sbt_res
+argument, and the resulting precision is assigned to
+.Fa *precision_res .
+When passing the results to
+.Fa callout_reset ,
+add the
+.Va C_PRECALC
+flag to
+.Fa flags ,
+to avoid incorrect re-adjustment.
+The function is intended for situations where precise time of the callout
+run should be known in advance, since
+trying to read this time from the callout structure itself after a
+.Fn callout_reset
+call is racy.
 .Sh CALLOUT FUNCTION RETURN VALUES
 .Bl -tag -width ".Dv CALLOUT_RET_CANCELLED"
 .It CALLOUT_RET_DRAINING

Modified: projects/hps_head/sys/kern/kern_timeout.c
==============================================================================
--- projects/hps_head/sys/kern/kern_timeout.c	Wed Aug 10 14:00:07 2016	(r303917)
+++ projects/hps_head/sys/kern/kern_timeout.c	Wed Aug 10 14:31:32 2016	(r303918)
@@ -1133,6 +1133,56 @@ callout_restart_async(struct callout *c,
 	return (retval);
 }
 
+void
+callout_when(sbintime_t sbt, sbintime_t precision, int flags,
+    sbintime_t *res, sbintime_t *prec_res)
+{
+	sbintime_t to_sbt, to_pr;
+
+	if ((flags & (C_ABSOLUTE | C_PRECALC)) != 0) {
+		*res = sbt;
+		*prec_res = precision;
+		return;
+	}
+	if ((flags & C_HARDCLOCK) != 0 && sbt < tick_sbt)
+		sbt = tick_sbt;
+	if ((flags & C_HARDCLOCK) != 0 ||
+#ifdef NO_EVENTTIMERS
+	    sbt >= sbt_timethreshold) {
+		to_sbt = getsbinuptime();
+
+		/* Add safety belt for the case of hz > 1000. */
+		to_sbt += tc_tick_sbt - tick_sbt;
+#else
+	    sbt >= sbt_tickthreshold) {
+		/*
+		 * Obtain the time of the last hardclock() call on
+		 * this CPU directly from the kern_clocksource.c.
+		 * This value is per-CPU, but it is equal for all
+		 * active ones.
+		 */
+#ifdef __LP64__
+		to_sbt = DPCPU_GET(hardclocktime);
+#else
+		spinlock_enter();
+		to_sbt = DPCPU_GET(hardclocktime);
+		spinlock_exit();
+#endif
+#endif
+		if ((flags & C_HARDCLOCK) == 0)
+			to_sbt += tick_sbt;
+	} else
+		to_sbt = sbinuptime();
+	if (SBT_MAX - to_sbt < sbt)
+		to_sbt = SBT_MAX;
+	else
+		to_sbt += sbt;
+	*res = to_sbt;
+	to_pr = ((C_PRELGET(flags) < 0) ? sbt >> tc_precexp :
+	    sbt >> C_PRELGET(flags));
+	*prec_res = to_pr > precision ? to_pr : precision;
+}
+
 /*
  * New interface; clients allocate their own callout structures.
  *
@@ -1150,7 +1200,7 @@ callout_restart_async(struct callout *c,
  * callout_deactivate() - marks the callout as having been serviced
  */
 int
-callout_reset_sbt_on(struct callout *c, sbintime_t sbt, sbintime_t precision,
+callout_reset_sbt_on(struct callout *c, sbintime_t sbt, sbintime_t prec,
     callout_func_t *ftn, void *arg, int cpu, int flags)
 {
 	struct callout_args coa;
@@ -1158,54 +1208,11 @@ callout_reset_sbt_on(struct callout *c, 
 	/* store arguments for callout add function */
 	coa.func = ftn;
 	coa.arg = arg;
-	coa.precision = precision;
 	coa.flags = flags;
 	coa.cpu = cpu;
 
-	/* compute the rest of the arguments needed */
-	if (coa.flags & C_ABSOLUTE) {
-		coa.time = sbt;
-	} else {
-		sbintime_t pr;
-
-		if ((coa.flags & C_HARDCLOCK) && (sbt < tick_sbt))
-			sbt = tick_sbt;
-		if ((coa.flags & C_HARDCLOCK) ||
-#ifdef NO_EVENTTIMERS
-		    sbt >= sbt_timethreshold) {
-			coa.time = getsbinuptime();
-
-			/* Add safety belt for the case of hz > 1000. */
-			coa.time += tc_tick_sbt - tick_sbt;
-#else
-		    sbt >= sbt_tickthreshold) {
-			/*
-			 * Obtain the time of the last hardclock() call on
-			 * this CPU directly from the kern_clocksource.c.
-			 * This value is per-CPU, but it is equal for all
-			 * active ones.
-			 */
-#ifdef __LP64__
-			coa.time = DPCPU_GET(hardclocktime);
-#else
-			spinlock_enter();
-			coa.time = DPCPU_GET(hardclocktime);
-			spinlock_exit();
-#endif
-#endif
-			if ((coa.flags & C_HARDCLOCK) == 0)
-				coa.time += tick_sbt;
-		} else
-			coa.time = sbinuptime();
-		if (SBT_MAX - coa.time < sbt)
-			coa.time = SBT_MAX;
-		else
-			coa.time += sbt;
-		pr = ((C_PRELGET(coa.flags) < 0) ? sbt >> tc_precexp :
-		    sbt >> C_PRELGET(coa.flags));
-		if (pr > coa.precision)
-			coa.precision = pr;
-	}
+	/* compute trigger time for callout */
+	callout_when(sbt, prec, flags, &coa.time, &coa.precision);
 
 	/* get callback started, if any */
 	return (callout_restart_async(c, &coa, NULL));

Modified: projects/hps_head/sys/sys/callout.h
==============================================================================
--- projects/hps_head/sys/sys/callout.h	Wed Aug 10 14:00:07 2016	(r303917)
+++ projects/hps_head/sys/sys/callout.h	Wed Aug 10 14:31:32 2016	(r303918)
@@ -64,6 +64,7 @@
 #define	C_PRELGET(x)		(int)((((x) >> 1) & C_PRELRANGE) - 1)
 #define	C_HARDCLOCK		0x0100 /* align to hardclock() calls */
 #define	C_ABSOLUTE		0x0200 /* event time is absolute. */
+#define	C_PRECALC		0x0400 /* event time is pre-calculated. */
 
 struct callout_handle {
 	struct callout *callout;
@@ -113,6 +114,7 @@ int	callout_schedule_on(struct callout *
 #define	callout_schedule_curcpu(c, on_tick)				\
     callout_schedule_on((c), (on_tick), PCPU_GET(cpuid))
 int	callout_stop(struct callout *);
+void	callout_when(sbintime_t, sbintime_t, int, sbintime_t *, sbintime_t *);
 void	callout_process(sbintime_t now);
 
 #endif



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201608101431.u7AEVW88096940>