svn commit: r304900 - in stable/10: share/man/man9 sys/kern sys/sys
Konstantin Belousov
kib at FreeBSD.org
Sat Aug 27 11:38:39 UTC 2016
Author: kib
Date: Sat Aug 27 11:38:37 2016
New Revision: 304900
URL: https://svnweb.freebsd.org/changeset/base/304900
Log:
MFC r303425:
Add callout_when(9).
MFC r303919:
Fix indentation.
Modified:
stable/10/share/man/man9/Makefile
stable/10/share/man/man9/timeout.9
stable/10/sys/kern/kern_timeout.c
stable/10/sys/sys/callout.h
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/share/man/man9/Makefile
==============================================================================
--- stable/10/share/man/man9/Makefile Sat Aug 27 11:38:21 2016 (r304899)
+++ stable/10/share/man/man9/Makefile Sat Aug 27 11:38:37 2016 (r304900)
@@ -1401,6 +1401,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 crcopy.9 \
ucred.9 crdup.9 \
Modified: stable/10/share/man/man9/timeout.9
==============================================================================
--- stable/10/share/man/man9/timeout.9 Sat Aug 27 11:38:21 2016 (r304899)
+++ stable/10/share/man/man9/timeout.9 Sat Aug 27 11:38:37 2016 (r304900)
@@ -29,7 +29,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 8, 2014
+.Dd July 27, 2016
.Dt TIMEOUT 9
.Os
.Sh NAME
@@ -55,6 +55,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
@@ -88,20 +89,48 @@ struct callout_handle handle = CALLOUT_H
.Ft int
.Fn callout_reset "struct callout *c" "int ticks" "timeout_t *func" "void *arg"
.Ft int
-.Fn callout_reset_curcpu "struct callout *c" "int ticks" "timeout_t *func" \
-"void *arg"
-.Ft int
-.Fn callout_reset_on "struct callout *c" "int ticks" "timeout_t *func" \
-"void *arg" "int cpu"
-.Ft int
-.Fn callout_reset_sbt "struct callout *c" "sbintime_t sbt" \
-"sbintime_t pr" "timeout_t *func" "void *arg" "int flags"
-.Ft int
-.Fn callout_reset_sbt_curcpu "struct callout *c" "sbintime_t sbt" \
-"sbintime_t pr" "timeout_t *func" "void *arg" "int flags"
-.Ft int
-.Fn callout_reset_sbt_on "struct callout *c" "sbintime_t sbt" \
-"sbintime_t pr" "timeout_t *func" "void *arg" "int cpu" "int flags"
+.Fo callout_reset_curcpu
+.Fa "struct callout *c"
+.Fa "int ticks"
+.Fa "timeout_t *func"
+.Fa "void *arg"
+.Fc
+.Ft int
+.Fo callout_reset_on
+.Fa "struct callout *c"
+.Fa "int ticks"
+.Fa "timeout_t *func"
+.Fa "void *arg"
+.Fa "int cpu"
+.Fc
+.Ft int
+.Fo callout_reset_sbt
+.Fa "struct callout *c"
+.Fa "sbintime_t sbt"
+.Fa "sbintime_t pr"
+.Fa "timeout_t *func"
+.Fa "void *arg"
+.Fa "int flags"
+.Fc
+.Ft int
+.Fo callout_reset_sbt_curcpu
+.Fa "struct callout *c"
+.Fa "sbintime_t sbt"
+.Fa "sbintime_t pr"
+.Fa "timeout_t *func"
+.Fa "void *arg"
+.Fa "int flags"
+.Fc
+.Ft int
+.Fo callout_reset_sbt_on
+.Fa "struct callout *c"
+.Fa "sbintime_t sbt"
+.Fa "sbintime_t pr"
+.Fa "timeout_t *func"
+.Fa "void *arg"
+.Fa "int cpu"
+.Fa "int flags"
+.Fc
.Ft int
.Fn callout_schedule "struct callout *c" "int ticks"
.Ft int
@@ -109,16 +138,37 @@ struct callout_handle handle = CALLOUT_H
.Ft int
.Fn callout_schedule_on "struct callout *c" "int ticks" "int cpu"
.Ft int
-.Fn callout_schedule_sbt "struct callout *c" "sbintime_t sbt" \
-"sbintime_t pr" "int flags"
-.Ft int
-.Fn callout_schedule_sbt_curcpu "struct callout *c" "sbintime_t sbt" \
-"sbintime_t pr" "int flags"
-.Ft int
-.Fn callout_schedule_sbt_on "struct callout *c" "sbintime_t sbt" \
-"sbintime_t pr" "int cpu" "int flags"
+.Fo callout_schedule_sbt
+.Fa "struct callout *c"
+.Fa "sbintime_t sbt"
+.Fa "sbintime_t pr"
+.Fa "int flags"
+.Fc
+.Ft int
+.Fo callout_schedule_sbt_curcpu
+.Fa "struct callout *c"
+.Fa "sbintime_t sbt"
+.Fa "sbintime_t pr"
+.Fa "int flags"
+.Fc
+.Ft int
+.Fo callout_schedule_sbt_on
+.Fa "struct callout *c"
+.Fa "sbintime_t sbt"
+.Fa "sbintime_t pr"
+.Fa "int cpu"
+.Fa "int flags"
+.Fc
.Ft int
.Fn callout_stop "struct callout *c"
+.Ft sbintime_t
+.Fo callout_when
+.Fa "sbintime_t sbt"
+.Fa "sbintime_t precision"
+.Fa "int flags"
+.Fa "sbintime_t *sbt_res"
+.Fa "sbintime_t *precision_res"
+.Fc
.Ft struct callout_handle
.Fn timeout "timeout_t *func" "void *arg" "int ticks"
.Ft void
@@ -354,6 +404,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
@@ -470,6 +540,39 @@ but it
.Em does not
clear it when a callout expires normally via the execution of the
callout function.
+.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.
.Ss "Avoiding Race Conditions"
The callout subsystem invokes callout functions from its own thread
context.
Modified: stable/10/sys/kern/kern_timeout.c
==============================================================================
--- stable/10/sys/kern/kern_timeout.c Sat Aug 27 11:38:21 2016 (r304899)
+++ stable/10/sys/kern/kern_timeout.c Sat Aug 27 11:38:37 2016 (r304900)
@@ -896,6 +896,56 @@ callout_handle_init(struct callout_handl
handle->callout = NULL;
}
+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.
*
@@ -913,10 +963,10 @@ callout_handle_init(struct callout_handl
* 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,
void (*ftn)(void *), void *arg, int cpu, int flags)
{
- sbintime_t to_sbt, pr;
+ sbintime_t to_sbt, precision;
struct callout_cpu *cc;
int cancelled, direct;
int ignore_cpu=0;
@@ -929,47 +979,8 @@ callout_reset_sbt_on(struct callout *c,
/* Invalid CPU spec */
panic("Invalid CPU in callout %d", cpu);
}
- if (flags & C_ABSOLUTE) {
- to_sbt = sbt;
- } else {
- if ((flags & C_HARDCLOCK) && (sbt < tick_sbt))
- sbt = tick_sbt;
- if ((flags & C_HARDCLOCK) ||
-#ifdef NO_EVENTTIMERS
- sbt >= sbt_timethreshold) {
- to_sbt = getsbinuptime();
+ callout_when(sbt, prec, flags, &to_sbt, &precision);
- /* 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;
- pr = ((C_PRELGET(flags) < 0) ? sbt >> tc_precexp :
- sbt >> C_PRELGET(flags));
- if (pr > precision)
- precision = pr;
- }
/*
* This flag used to be added by callout_cc_add, but the
* first time you call this we could end up with the
Modified: stable/10/sys/sys/callout.h
==============================================================================
--- stable/10/sys/sys/callout.h Sat Aug 27 11:38:21 2016 (r304899)
+++ stable/10/sys/sys/callout.h Sat Aug 27 11:38:37 2016 (r304900)
@@ -57,6 +57,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;
@@ -129,6 +130,8 @@ int callout_schedule_on(struct callout *
int _callout_stop_safe(struct callout *, int);
void callout_process(sbintime_t now);
+void callout_when(sbintime_t sbt, sbintime_t precision, int flags,
+ sbintime_t *sbt_res, sbintime_t *prec_res);
#endif
#endif /* _SYS_CALLOUT_H_ */
More information about the svn-src-all
mailing list