| CALLOUT(9) | Kernel Developer's Manual | CALLOUT(9) | 
callout_init, callout_destroy,
  callout_halt, callout_reset,
  callout_schedule,
  callout_setfunc, callout_stop,
  callout_pending,
  callout_expired,
  callout_invoking, callout_ack
  —
#include <sys/callout.h>
void
  
  callout_init(callout_t
    *c, u_int
  flags);
void
  
  callout_destroy(callout_t
    *c);
void
  
  callout_reset(callout_t
    *c, int ticks,
    void (*func)(void *),
    void *arg);
void
  
  callout_schedule(callout_t
    *c, int ticks);
void
  
  callout_setfunc(callout_t
    *c, void (*func)(void
    *), void *arg);
bool
  
  callout_stop(callout_t
    *c);
bool
  
  callout_halt(callout_t
    *c, void
    *interlock);
bool
  
  callout_pending(callout_t
    *c);
bool
  
  callout_expired(callout_t
    *c);
bool
  
  callout_active(callout_t
    *c);
bool
  
  callout_invoking(callout_t
    *c);
void
  
  callout_ack(callout_t
    *c);
callout facility provides a mechanism to execute a
  function at a given time. The timer is based on the hardclock timer which
  ticks hz times per second. The function is called at
  softclock interrupt level.
Clients of the callout facility are
    responsible for providing pre-allocated callout structures, or
    “handles”. The callout facility
    replaces the historic UNIX functions
    timeout() and
  untimeout().
callout_init() function initializes the callout
  handle c for use. No operations can be performed on the
  callout before it is initialized. If the flags argument
  is 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.
callout_destroy() destroys the callout,
    preventing further use. It is provided as a diagnostic facility intended to
    catch bugs. To ensure future compatibility,
    callout_destroy() should always be called when the
    callout is no longer required (for instance, when a device is being
    detached). The callout should be stopped before
    callout_destroy() is called by calling
    callout_halt(). Note that
    callout_stop() shouldn't be used for this
  purpose.
The callout_reset() function resets and
    starts the timer associated with the callout handle c.
    When the timer expires after
    ticks/hz seconds, the function
    specified by func will be called with the argument
    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 PENDING. Once the timer expires, the handle is
    marked as EXPIRED and INVOKING, and the
    PENDING status is cleared.
The callout_setfunc() function sets the
    function and argument of the callout handle c to
    func and arg respectively. The
    callout handle must already be initialized. If a callout will always be used
    with the same function and argument, then
    callout_setfunc() used in conjunction with
    callout_schedule() is slightly more efficient than
    using callout_reset().
The callout_stop() function requests that
    the timer associated with the callout handle c be
    stopped. The PENDING and EXPIRED status
    for the callout handle is cleared. It is safe to call
    callout_stop() on a callout handle that is not
    pending, so long as it is initialized.
    callout_stop() will return a non-zero value if the
    callout was EXPIRED. Note that
    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 callout_halt().
callout_halt() acts much like
    callout_stop(), but waits for the callout to
    complete if it is currently in-flight.
    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
    callout_halt() must not hold any of those locks,
    otherwise the two could deadlock. To facilitate this,
    callout_halt() can optionally release a single mutex
    specified by the interlock parameter. If
    interlock is not NULL and the
    calling thread must wait for the callout to complete,
    interlock will be released before waiting and
    re-acquired before returning. If no wait is required,
    interlock will not be released. However, to avoid race
    conditions the caller should always assume that
    interlock has been released and reacquired, and act
    accordingly.
The callout_pending() function tests the
    PENDING status of the callout handle
    c. A 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
    PENDING status when at softclock interrupt level or
    higher.
The callout_expired() function tests to
    see if the callout's timer has expired and its function called.
The callout_active() function returns true
    if a timer has been started but not explicitly stopped, even if it has
    already fired.
    callout_active(foo) is
    logically the same as
    callout_pending(foo) ||
    callout_expired(foo); it is
    implemented as a separate function for compatibility with
    FreeBSD and for the special case of
    TCP_TIMER_ISARMED(). Its use is not recommended.
The callout_invoking() function tests the
    INVOKING status of the callout handle
    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 INVOKING state
    using 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 callout_ack() function to clear
    this flag.
The callout_ack() function clears the
    INVOKING state in the callout handle
    c. This is used in situations where it is necessary to
    protect against the race condition described under
    callout_invoking().
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.
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 NetBSD kernel by Jason R.
  Thorpe.
| January 12, 2020 | NetBSD 10.0 |