svn commit: r303918 - in projects/hps_head: share/man/man9 sys/kern sys/sys
Hans Petter Selasky
hselasky at FreeBSD.org
Wed Aug 10 14:31:34 UTC 2016
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
More information about the svn-src-projects
mailing list