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>