316 lines
9.4 KiB
Groff
316 lines
9.4 KiB
Groff
.\" $NetBSD: callout.9,v 1.25 2009/08/03 23:29:19 rmind Exp $
|
|
.\"
|
|
.\" Copyright (c) 2000, 2003, 2009 The NetBSD Foundation, Inc.
|
|
.\" All rights reserved.
|
|
.\"
|
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
|
.\" by Jason R. Thorpe.
|
|
.\"
|
|
.\" Redistribution and use in source and binary forms, with or without
|
|
.\" modification, are permitted provided that the following conditions
|
|
.\" are met:
|
|
.\" 1. Redistributions of source code must retain the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer.
|
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer in the
|
|
.\" documentation and/or other materials provided with the distribution.
|
|
.\"
|
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
|
.\"
|
|
.Dd August 3, 2009
|
|
.Dt CALLOUT 9
|
|
.Os
|
|
.Sh NAME
|
|
.Nm callout_init ,
|
|
.Nm callout_destroy ,
|
|
.Nm callout_halt ,
|
|
.Nm callout_reset ,
|
|
.Nm callout_schedule ,
|
|
.Nm callout_setfunc ,
|
|
.Nm callout_stop ,
|
|
.Nm callout_pending ,
|
|
.Nm callout_expired ,
|
|
.Nm callout_invoking ,
|
|
.Nm callout_ack
|
|
.Nd execute a function after a specified length of time
|
|
.Sh SYNOPSIS
|
|
.In sys/callout.h
|
|
.Ft void
|
|
.Fn "callout_init" "callout_t *c" "u_int flags"
|
|
.Ft void
|
|
.Fn "callout_destroy" "callout_t *c"
|
|
.Ft void
|
|
.Fn "callout_reset" "callout_t *c" "int ticks" \
|
|
"void (*func)(void *)" "void *arg"
|
|
.Ft void
|
|
.Fn "callout_schedule" "callout_t *c" "int ticks"
|
|
.Ft void
|
|
.Fn "callout_setfunc" "callout_t *c" "void (*func)(void *)" "void *arg"
|
|
.Ft bool
|
|
.Fn "callout_stop" "callout_t *c"
|
|
.Ft bool
|
|
.Fn "callout_halt" "callout_t *c" "kmutex_t *interlock"
|
|
.Ft bool
|
|
.Fn "callout_pending" "callout_t *c"
|
|
.Ft bool
|
|
.Fn "callout_expired" "callout_t *c"
|
|
.Ft bool
|
|
.Fn "callout_active" "callout_t *c"
|
|
.Ft bool
|
|
.Fn "callout_invoking" "callout_t *c"
|
|
.Ft bool
|
|
.Fn "callout_ack" "callout_t *c"
|
|
.Sh DESCRIPTION
|
|
The
|
|
.Nm callout
|
|
facility provides a mechanism to execute a function at a given time.
|
|
The timer is based on the hardclock timer which ticks
|
|
.Dv hz
|
|
times per second.
|
|
The function is called at softclock interrupt level.
|
|
.Pp
|
|
Clients of the
|
|
.Nm callout
|
|
facility are responsible for providing pre-allocated
|
|
callout structures, or
|
|
.Dq handles .
|
|
The
|
|
.Nm callout
|
|
facility replaces the historic
|
|
.Ux
|
|
functions
|
|
.Fn timeout
|
|
and
|
|
.Fn untimeout .
|
|
.Sh FUNCTIONS
|
|
The
|
|
.Fn callout_init
|
|
function initializes the callout handle
|
|
.Fa c
|
|
for use.
|
|
No operations can be performed on the callout before it is initialized.
|
|
If the
|
|
.Fa flags
|
|
argument is
|
|
.Dv CALLOUT_MPSAFE ,
|
|
the handler will be called without getting the global kernel lock.
|
|
In this case it should only use functions that are multiprocessor
|
|
safe.
|
|
.Pp
|
|
.Fn callout_destroy
|
|
destroys the callout, preventing further use.
|
|
It is provided as a diagnostic facility intended to catch bugs.
|
|
To ensure future compatibility,
|
|
.Fn callout_destroy
|
|
should always be called when the callout is no longer required (for instance,
|
|
when a device is being detached).
|
|
.Pp
|
|
The
|
|
.Fn callout_reset
|
|
function resets and starts the timer associated with the callout handle
|
|
.Fa c .
|
|
When the timer expires after
|
|
.Fa ticks Ns No /hz
|
|
seconds, the function specified by
|
|
.Fa func
|
|
will be called with the argument
|
|
.Fa arg .
|
|
If the timer associated with the callout handle is already running,
|
|
the callout will simply be rescheduled to execute at the newly specified
|
|
time.
|
|
Once the timer is started, the callout handle is marked as
|
|
.Em PENDING .
|
|
Once the timer expires,
|
|
the handle is marked as
|
|
.Em EXPIRED
|
|
and
|
|
.Em INVOKING ,
|
|
and the
|
|
.Em PENDING
|
|
status is cleared.
|
|
.Pp
|
|
The
|
|
.Fn callout_setfunc
|
|
function sets the function and argument of the callout handle
|
|
.Fa c
|
|
to
|
|
.Fa func
|
|
and
|
|
.Fa arg
|
|
respectively.
|
|
The callout handle must already be initialized.
|
|
If a callout will always be used with the same function and argument,
|
|
then
|
|
.Fn callout_setfunc
|
|
used in conjunction with
|
|
.Fn callout_schedule
|
|
is slightly more efficient than using
|
|
.Fn callout_reset .
|
|
.Pp
|
|
The
|
|
.Fn callout_stop
|
|
function requests that the timer associated with the callout handle
|
|
.Fa c
|
|
be stopped.
|
|
The
|
|
.Em PENDING
|
|
and
|
|
.Em EXPIRED
|
|
status for the callout handle is cleared.
|
|
It is safe to call
|
|
.Fn callout_stop
|
|
on a callout handle that is not pending, so long as it is initialized.
|
|
.Fn callout_stop
|
|
will return a non-zero value if the callout was
|
|
.Em EXPIRED .
|
|
Note that
|
|
.Fn callout_stop
|
|
can return while the callout is running on a different CPU or at a
|
|
different interrupt priority level on the current CPU.
|
|
It can only be said to prevent the callout from firing in the future,
|
|
unless explicitly re-scheduled.
|
|
To stop a callout and wait for completion, use
|
|
.Fn callout_halt .
|
|
.Pp
|
|
.Fn callout_halt
|
|
acts much like
|
|
.Fn callout_stop ,
|
|
but waits for the callout to complete if it is currently in-flight.
|
|
.Fn callout_halt
|
|
may not be called from a hard interrupt handler as it will sleep if the
|
|
callout is currently executing.
|
|
If the callout can take locks (such as mutexes or RW locks), the caller of
|
|
.Fn callout_halt
|
|
must not hold any of those locks, otherwise the two could deadlock.
|
|
To facilitate this,
|
|
.Fn callout_halt
|
|
can optionally release a single mutex specified by the
|
|
.Fa interlock
|
|
parameter.
|
|
If
|
|
.Fa interlock
|
|
is not
|
|
.Dv NULL
|
|
and the calling thread must wait for the callout to complete,
|
|
.Fa interlock
|
|
will be released before waiting and re-acquired before returning.
|
|
If no wait is required,
|
|
.Fa interlock
|
|
will not be released.
|
|
However, to avoid race conditions the caller should always assume that
|
|
.Fa interlock
|
|
has been released and reacquired, and act accordingly.
|
|
.Pp
|
|
The
|
|
.Fn callout_pending
|
|
function tests the
|
|
.Em PENDING
|
|
status of the callout handle
|
|
.Fa c .
|
|
A
|
|
.Em PENDING
|
|
callout is one that has been started and whose function has not yet
|
|
been called.
|
|
Note that it is possible for a callout's timer to have expired without
|
|
its function being called if interrupt level has not dropped low enough
|
|
to let softclock interrupts through.
|
|
Note that it is only safe to test
|
|
.Em PENDING
|
|
status when at softclock interrupt level or higher.
|
|
.Pp
|
|
The
|
|
.Fn callout_expired
|
|
function tests to see if the callout's timer has expired and its
|
|
function called.
|
|
.Pp
|
|
The
|
|
.Fn callout_active
|
|
function returns true if a timer has been started but not explicitly stopped,
|
|
even if it has already fired.
|
|
.Fn callout_active foo
|
|
is logically the same as
|
|
.Fn callout_pending foo
|
|
||
|
|
.Fn callout_expired foo ;
|
|
it is implemented as a separate function for compatibility with
|
|
.Fx
|
|
and for the special case of
|
|
.Fn TCP_TIMER_ISARMED .
|
|
Its use is not recommended.
|
|
.Pp
|
|
The
|
|
.Fn callout_invoking
|
|
function tests the
|
|
.Em INVOKING
|
|
status of the callout handle
|
|
.Fa c .
|
|
This flag is set just before a callout's function is being called.
|
|
Since the priority level is lowered prior to invocation of the
|
|
callout function, other pending higher-priority code may run before
|
|
the callout function is allowed to run.
|
|
This may create a race condition if this higher-priority code
|
|
deallocates storage containing one or more callout structures whose
|
|
callout functions are about to be run.
|
|
In such cases, one technique to prevent references to deallocated
|
|
storage would be to test whether any callout functions are in the
|
|
.Em INVOKING
|
|
state using
|
|
.Fn callout_invoking ,
|
|
and if so, to mark the data structure and defer storage
|
|
deallocation until the callout function is allowed to run.
|
|
For this handshake protocol to work, the callout function will
|
|
have to use the
|
|
.Fn callout_ack
|
|
function to clear this flag.
|
|
.Pp
|
|
The
|
|
.Fn callout_ack
|
|
function clears the
|
|
.Em INVOKING
|
|
state in the callout handle
|
|
.Fa c .
|
|
This is used in situations where it is necessary to protect against
|
|
the race condition described under
|
|
.Fn callout_invoking .
|
|
.Sh CONCURRENCY
|
|
The callout facility performs locking internally in order to guarantee the
|
|
atomicity of individual operations performed on callouts.
|
|
It does not provide life cycle management of user-provided callout data
|
|
structures, nor does it ensure that groups of operations (multiple function
|
|
calls) are performed atomically.
|
|
These aspects of callout management are the responsibility of the user of
|
|
the callout facility.
|
|
.Pp
|
|
Scheduled callouts may be active concurrently in a context different to the
|
|
user of the callout facility: on another CPU, or at a different interrupt
|
|
priority level or thread on the current CPU.
|
|
The callout facility provides only one guarantee in this regard: any given
|
|
callout will never have multiple concurrent invocations.
|
|
.Sh SEE ALSO
|
|
.Xr condvar 9 ,
|
|
.Xr hz 9 ,
|
|
.Xr softint 9 ,
|
|
.Xr workqueue 9
|
|
.Sh HISTORY
|
|
The
|
|
.Nm callout
|
|
facility was implemented by Artur Grabowski and Thomas Nordin, based
|
|
on the work of G. Varghese and A. Lauck, described in the paper
|
|
Hashed and Hierarchical Timing Wheels: Data Structures for the
|
|
Efficient Implementation of a Timer Facility
|
|
in the Proceedings of the 11th ACM Annual Symposium on Operating System
|
|
Principles, Austin, Texas, November 1987.
|
|
It was adapted to the
|
|
.Nx
|
|
kernel by Jason R. Thorpe.
|