timeout, untimeout, callout_handle_init, callout_init, callout_stop,
callout_reset -- execute a function after a specified length of time
#include <sys/types.h>
#include <sys/systm.h>
typedef void timeout_t (void *);
struct callout_handle
timeout(timeout_t *func, void *arg, int ticks);
void
callout_handle_init(struct callout_handle *handle);
struct callout_handle handle = CALLOUT_HANDLE_INITIALIZER(&handle)
void
untimeout(timeout_t *func, void *arg, struct callout_handle handle);
void
callout_init(struct callout *c, int mpsafe);
int
callout_stop(struct callout *c);
void
callout_reset(struct callout *c, int ticks, timeout_t *func, void *arg);
The function timeout() schedules a call to the function given by the
argument func to take place after ticks/hz seconds. Non-positive values
of ticks are silently converted to the value `1'. func should be a
pointer to a function that takes a void * argument. Upon invocation,
func will receive arg as its only argument. The return value from
timeout() is a struct callout_handle which can be used in conjunction
with the untimeout() function to request that a scheduled timeout be canceled.
The timeout() call is the old style and new code should use the
callout_* functions.
The function callout_handle_init() can be used to initialize a handle to
a state which will cause any calls to untimeout with that handle to
return with no side effects.
Assigning a callout handle the value of CALLOUT_HANDLE_INITIALIZER() performs
the same function as callout_handle_init() and is provided for use
on statically declared or global callout handles.
The function untimeout() cancels the timeout associated with handle using
the func and arg arguments to validate the handle. If the handle does
not correspond to a timeout with the function func taking the argument
arg no action is taken. handle must be initialized by a previous call to
timeout(), callout_handle_init(), or assigned the value of
CALLOUT_HANDLE_INITIALIZER(&handle) before being passed to untimeout().
The behavior of calling untimeout without a previously initialized handle
is undefined. The untimeout() call is the old style and new code should
use the callout_* functions.
As handles are recycled by the system, it is possible (although unlikely)
that a handle from one invocation of timeout() may match the handle of
another invocation of timeout() if both calls used the same function
pointer and argument, and the first timeout is expired or canceled before
the second call. The timeout facility offers O(1) running time for
timeout() and untimeout(). Timeouts are executed from softclock() at
splsoftclock(). Thus they are protected from re-entrancy.
The functions callout_init(), callout_stop() and callout_reset() are lowlevel
routines for clients who wish to allocate their own callout structures.
The function callout_init() initializes a callout so it can be passed to
callout_stop() or callout_reset() without any side effects. If the
mpsafe argument is zero, the callout structure is not considered to be
``multi-processor safe''; that is, the Giant lock will be acquired before
calling the callout function, and released when the callout function
returns.
The function callout_stop() cancels a callout if it is currently pending.
If the callout is pending, then callout_stop() will return a non-zero
value. If the callout has already been serviced or is currently being
serviced, then zero will be returned.
The function callout_reset() first calls callout_stop() to disestablish
the callout, and then establishes a new callout in the same manner as
timeout().
The timeout() function returns a struct callout_handle that can be passed
to untimeout(). The callout_stop() function returns non-zero if the
callout was still pending when it was called or zero otherwise.
This API has no way to cancel a callout and ensure that if it was canceled
too late that the callout has actually finished. callout_stop()
only guarantees that the callout has started when it returns 0. It does
not guarantee that the callout has finished. This can create a race when
one wishes to ensure that no threads are executing before returning from
a driver detach routine.
The current timeout and untimeout routines are based on the work of Adam
M. Costello and George Varghese, published in a technical report entitled
Redesigning the BSD Callout and Timer Facilities and modified slightly
for inclusion in FreeBSD by Justin T. Gibbs. The original work on the
data structures used in this implementation was published by G. Varghese
and A. Lauck 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 Systems
Principles. The current implementation replaces the long standing BSD
linked list callout mechanism which offered O(n) insertion and removal
running time but did not generate or require handles for untimeout operations.
FreeBSD 5.2.1 September 10, 1996 FreeBSD 5.2.1 [ Back ] |