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_ */
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to