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) Sponsored by: The FreeBSD Foundation MFC after: 1 month X-Differential revision: https://reviews.freebsd.org/D7137
This commit is contained in:
parent
ad90086e85
commit
a9e182e895
@ -1766,6 +1766,7 @@ MLINKS+=timeout.9 callout.9 \
|
|||||||
timeout.9 callout_schedule_sbt_curcpu.9 \
|
timeout.9 callout_schedule_sbt_curcpu.9 \
|
||||||
timeout.9 callout_schedule_sbt_on.9 \
|
timeout.9 callout_schedule_sbt_on.9 \
|
||||||
timeout.9 callout_stop.9 \
|
timeout.9 callout_stop.9 \
|
||||||
|
timeout.9 callout_when.9 \
|
||||||
timeout.9 untimeout.9
|
timeout.9 untimeout.9
|
||||||
MLINKS+=ucred.9 cred_update_thread.9 \
|
MLINKS+=ucred.9 cred_update_thread.9 \
|
||||||
ucred.9 crcopy.9 \
|
ucred.9 crcopy.9 \
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd July 4, 2016
|
.Dd July 27, 2016
|
||||||
.Dt TIMEOUT 9
|
.Dt TIMEOUT 9
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -56,6 +56,7 @@
|
|||||||
.Nm callout_schedule_sbt_curcpu ,
|
.Nm callout_schedule_sbt_curcpu ,
|
||||||
.Nm callout_schedule_sbt_on ,
|
.Nm callout_schedule_sbt_on ,
|
||||||
.Nm callout_stop ,
|
.Nm callout_stop ,
|
||||||
|
.Nm callout_when ,
|
||||||
.Nm timeout ,
|
.Nm timeout ,
|
||||||
.Nm untimeout
|
.Nm untimeout
|
||||||
.Nd execute a function after a specified length of time
|
.Nd execute a function after a specified length of time
|
||||||
@ -91,20 +92,48 @@ struct callout_handle handle = CALLOUT_HANDLE_INITIALIZER(&handle);
|
|||||||
.Ft int
|
.Ft int
|
||||||
.Fn callout_reset "struct callout *c" "int ticks" "timeout_t *func" "void *arg"
|
.Fn callout_reset "struct callout *c" "int ticks" "timeout_t *func" "void *arg"
|
||||||
.Ft int
|
.Ft int
|
||||||
.Fn callout_reset_curcpu "struct callout *c" "int ticks" "timeout_t *func" \
|
.Fo callout_reset_curcpu
|
||||||
"void *arg"
|
.Fa "struct callout *c"
|
||||||
|
.Fa "int ticks"
|
||||||
|
.Fa "timeout_t *func"
|
||||||
|
.Fa "void *arg"
|
||||||
|
.Fc
|
||||||
.Ft int
|
.Ft int
|
||||||
.Fn callout_reset_on "struct callout *c" "int ticks" "timeout_t *func" \
|
.Fo callout_reset_on
|
||||||
"void *arg" "int cpu"
|
.Fa "struct callout *c"
|
||||||
|
.Fa "int ticks"
|
||||||
|
.Fa "timeout_t *func"
|
||||||
|
.Fa "void *arg"
|
||||||
|
.Fa "int cpu"
|
||||||
|
.Fc
|
||||||
.Ft int
|
.Ft int
|
||||||
.Fn callout_reset_sbt "struct callout *c" "sbintime_t sbt" \
|
.Fo callout_reset_sbt
|
||||||
"sbintime_t pr" "timeout_t *func" "void *arg" "int flags"
|
.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
|
.Ft int
|
||||||
.Fn callout_reset_sbt_curcpu "struct callout *c" "sbintime_t sbt" \
|
.Fo callout_reset_sbt_curcpu
|
||||||
"sbintime_t pr" "timeout_t *func" "void *arg" "int flags"
|
.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
|
.Ft int
|
||||||
.Fn callout_reset_sbt_on "struct callout *c" "sbintime_t sbt" \
|
.Fo callout_reset_sbt_on
|
||||||
"sbintime_t pr" "timeout_t *func" "void *arg" "int cpu" "int flags"
|
.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
|
.Ft int
|
||||||
.Fn callout_schedule "struct callout *c" "int ticks"
|
.Fn callout_schedule "struct callout *c" "int ticks"
|
||||||
.Ft int
|
.Ft int
|
||||||
@ -112,16 +141,37 @@ struct callout_handle handle = CALLOUT_HANDLE_INITIALIZER(&handle);
|
|||||||
.Ft int
|
.Ft int
|
||||||
.Fn callout_schedule_on "struct callout *c" "int ticks" "int cpu"
|
.Fn callout_schedule_on "struct callout *c" "int ticks" "int cpu"
|
||||||
.Ft int
|
.Ft int
|
||||||
.Fn callout_schedule_sbt "struct callout *c" "sbintime_t sbt" \
|
.Fo callout_schedule_sbt
|
||||||
"sbintime_t pr" "int flags"
|
.Fa "struct callout *c"
|
||||||
|
.Fa "sbintime_t sbt"
|
||||||
|
.Fa "sbintime_t pr"
|
||||||
|
.Fa "int flags"
|
||||||
|
.Fc
|
||||||
.Ft int
|
.Ft int
|
||||||
.Fn callout_schedule_sbt_curcpu "struct callout *c" "sbintime_t sbt" \
|
.Fo callout_schedule_sbt_curcpu
|
||||||
"sbintime_t pr" "int flags"
|
.Fa "struct callout *c"
|
||||||
|
.Fa "sbintime_t sbt"
|
||||||
|
.Fa "sbintime_t pr"
|
||||||
|
.Fa "int flags"
|
||||||
|
.Fc
|
||||||
.Ft int
|
.Ft int
|
||||||
.Fn callout_schedule_sbt_on "struct callout *c" "sbintime_t sbt" \
|
.Fo callout_schedule_sbt_on
|
||||||
"sbintime_t pr" "int cpu" "int flags"
|
.Fa "struct callout *c"
|
||||||
|
.Fa "sbintime_t sbt"
|
||||||
|
.Fa "sbintime_t pr"
|
||||||
|
.Fa "int cpu"
|
||||||
|
.Fa "int flags"
|
||||||
|
.Fc
|
||||||
.Ft int
|
.Ft int
|
||||||
.Fn callout_stop "struct callout *c"
|
.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
|
.Ft struct callout_handle
|
||||||
.Fn timeout "timeout_t *func" "void *arg" "int ticks"
|
.Fn timeout "timeout_t *func" "void *arg" "int ticks"
|
||||||
.Ft void
|
.Ft void
|
||||||
@ -387,6 +437,26 @@ or this value is used as the length of the time window.
|
|||||||
Smaller values
|
Smaller values
|
||||||
.Pq which result in larger time intervals
|
.Pq which result in larger time intervals
|
||||||
allow the callout subsystem to aggregate more events in one timer interrupt.
|
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
|
.It Dv C_HARDCLOCK
|
||||||
Align the timeouts to
|
Align the timeouts to
|
||||||
.Fn hardclock
|
.Fn hardclock
|
||||||
@ -503,6 +573,39 @@ but it
|
|||||||
.Em does not
|
.Em does not
|
||||||
clear it when a callout expires normally via the execution of the
|
clear it when a callout expires normally via the execution of the
|
||||||
callout function.
|
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"
|
.Ss "Avoiding Race Conditions"
|
||||||
The callout subsystem invokes callout functions from its own thread
|
The callout subsystem invokes callout functions from its own thread
|
||||||
context.
|
context.
|
||||||
|
@ -945,45 +945,20 @@ callout_handle_init(struct callout_handle *handle)
|
|||||||
handle->callout = NULL;
|
handle->callout = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void
|
||||||
* New interface; clients allocate their own callout structures.
|
callout_when(sbintime_t sbt, sbintime_t precision, int flags,
|
||||||
*
|
sbintime_t *res, sbintime_t *prec_res)
|
||||||
* callout_reset() - establish or change a timeout
|
|
||||||
* callout_stop() - disestablish a timeout
|
|
||||||
* callout_init() - initialize a callout structure so that it can
|
|
||||||
* safely be passed to callout_reset() and callout_stop()
|
|
||||||
*
|
|
||||||
* <sys/callout.h> defines three convenience macros:
|
|
||||||
*
|
|
||||||
* callout_active() - returns truth if callout has not been stopped,
|
|
||||||
* drained, or deactivated since the last time the callout was
|
|
||||||
* reset.
|
|
||||||
* callout_pending() - returns truth if callout is still waiting for timeout
|
|
||||||
* callout_deactivate() - marks the callout as having been serviced
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
callout_reset_sbt_on(struct callout *c, sbintime_t sbt, sbintime_t precision,
|
|
||||||
void (*ftn)(void *), void *arg, int cpu, int flags)
|
|
||||||
{
|
{
|
||||||
sbintime_t to_sbt, pr;
|
sbintime_t to_sbt, to_pr;
|
||||||
struct callout_cpu *cc;
|
|
||||||
int cancelled, direct;
|
|
||||||
int ignore_cpu=0;
|
|
||||||
|
|
||||||
cancelled = 0;
|
if ((flags & (C_ABSOLUTE | C_PRECALC)) != 0) {
|
||||||
if (cpu == -1) {
|
*res = sbt;
|
||||||
ignore_cpu = 1;
|
*prec_res = precision;
|
||||||
} else if ((cpu >= MAXCPU) ||
|
return;
|
||||||
((CC_CPU(cpu))->cc_inited == 0)) {
|
|
||||||
/* Invalid CPU spec */
|
|
||||||
panic("Invalid CPU in callout %d", cpu);
|
|
||||||
}
|
}
|
||||||
if (flags & C_ABSOLUTE) {
|
if ((flags & C_HARDCLOCK) != 0 && sbt < tick_sbt)
|
||||||
to_sbt = sbt;
|
|
||||||
} else {
|
|
||||||
if ((flags & C_HARDCLOCK) && (sbt < tick_sbt))
|
|
||||||
sbt = tick_sbt;
|
sbt = tick_sbt;
|
||||||
if ((flags & C_HARDCLOCK) ||
|
if ((flags & C_HARDCLOCK) != 0 ||
|
||||||
#ifdef NO_EVENTTIMERS
|
#ifdef NO_EVENTTIMERS
|
||||||
sbt >= sbt_timethreshold) {
|
sbt >= sbt_timethreshold) {
|
||||||
to_sbt = getsbinuptime();
|
to_sbt = getsbinuptime();
|
||||||
@ -1014,11 +989,47 @@ callout_reset_sbt_on(struct callout *c, sbintime_t sbt, sbintime_t precision,
|
|||||||
to_sbt = SBT_MAX;
|
to_sbt = SBT_MAX;
|
||||||
else
|
else
|
||||||
to_sbt += sbt;
|
to_sbt += sbt;
|
||||||
pr = ((C_PRELGET(flags) < 0) ? sbt >> tc_precexp :
|
*res = to_sbt;
|
||||||
|
to_pr = ((C_PRELGET(flags) < 0) ? sbt >> tc_precexp :
|
||||||
sbt >> C_PRELGET(flags));
|
sbt >> C_PRELGET(flags));
|
||||||
if (pr > precision)
|
*prec_res = to_pr > precision ? to_pr : precision;
|
||||||
precision = pr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* New interface; clients allocate their own callout structures.
|
||||||
|
*
|
||||||
|
* callout_reset() - establish or change a timeout
|
||||||
|
* callout_stop() - disestablish a timeout
|
||||||
|
* callout_init() - initialize a callout structure so that it can
|
||||||
|
* safely be passed to callout_reset() and callout_stop()
|
||||||
|
*
|
||||||
|
* <sys/callout.h> defines three convenience macros:
|
||||||
|
*
|
||||||
|
* callout_active() - returns truth if callout has not been stopped,
|
||||||
|
* drained, or deactivated since the last time the callout was
|
||||||
|
* reset.
|
||||||
|
* callout_pending() - returns truth if callout is still waiting for timeout
|
||||||
|
* callout_deactivate() - marks the callout as having been serviced
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
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, precision;
|
||||||
|
struct callout_cpu *cc;
|
||||||
|
int cancelled, direct;
|
||||||
|
int ignore_cpu=0;
|
||||||
|
|
||||||
|
cancelled = 0;
|
||||||
|
if (cpu == -1) {
|
||||||
|
ignore_cpu = 1;
|
||||||
|
} else if ((cpu >= MAXCPU) ||
|
||||||
|
((CC_CPU(cpu))->cc_inited == 0)) {
|
||||||
|
/* Invalid CPU spec */
|
||||||
|
panic("Invalid CPU in callout %d", cpu);
|
||||||
|
}
|
||||||
|
callout_when(sbt, prec, flags, &to_sbt, &precision);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This flag used to be added by callout_cc_add, but the
|
* This flag used to be added by callout_cc_add, but the
|
||||||
* first time you call this we could end up with the
|
* first time you call this we could end up with the
|
||||||
|
@ -57,6 +57,7 @@
|
|||||||
#define C_PRELGET(x) (int)((((x) >> 1) & C_PRELRANGE) - 1)
|
#define C_PRELGET(x) (int)((((x) >> 1) & C_PRELRANGE) - 1)
|
||||||
#define C_HARDCLOCK 0x0100 /* align to hardclock() calls */
|
#define C_HARDCLOCK 0x0100 /* align to hardclock() calls */
|
||||||
#define C_ABSOLUTE 0x0200 /* event time is absolute. */
|
#define C_ABSOLUTE 0x0200 /* event time is absolute. */
|
||||||
|
#define C_PRECALC 0x0400 /* event time is pre-calculated. */
|
||||||
|
|
||||||
struct callout_handle {
|
struct callout_handle {
|
||||||
struct callout *callout;
|
struct callout *callout;
|
||||||
@ -129,6 +130,8 @@ int _callout_stop_safe(struct callout *, int, void (*)(void *));
|
|||||||
void callout_process(sbintime_t now);
|
void callout_process(sbintime_t now);
|
||||||
#define callout_async_drain(c, d) \
|
#define callout_async_drain(c, d) \
|
||||||
_callout_stop_safe(c, 0, d)
|
_callout_stop_safe(c, 0, d)
|
||||||
|
void callout_when(sbintime_t sbt, sbintime_t precision, int flags,
|
||||||
|
sbintime_t *sbt_res, sbintime_t *prec_res);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _SYS_CALLOUT_H_ */
|
#endif /* _SYS_CALLOUT_H_ */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user