kern_timeout.c revision 81481
11541Srgrimes/*-
21541Srgrimes * Copyright (c) 1982, 1986, 1991, 1993
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes * (c) UNIX System Laboratories, Inc.
51541Srgrimes * All or some portions of this file are derived from material licensed
61541Srgrimes * to the University of California by American Telephone and Telegraph
71541Srgrimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with
81541Srgrimes * the permission of UNIX System Laboratories, Inc.
91541Srgrimes *
101541Srgrimes * Redistribution and use in source and binary forms, with or without
111541Srgrimes * modification, are permitted provided that the following conditions
121541Srgrimes * are met:
131541Srgrimes * 1. Redistributions of source code must retain the above copyright
141541Srgrimes *    notice, this list of conditions and the following disclaimer.
151541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
161541Srgrimes *    notice, this list of conditions and the following disclaimer in the
171541Srgrimes *    documentation and/or other materials provided with the distribution.
181541Srgrimes * 3. All advertising materials mentioning features or use of this software
191541Srgrimes *    must display the following acknowledgement:
201541Srgrimes *	This product includes software developed by the University of
211541Srgrimes *	California, Berkeley and its contributors.
221541Srgrimes * 4. Neither the name of the University nor the names of its contributors
231541Srgrimes *    may be used to endorse or promote products derived from this software
241541Srgrimes *    without specific prior written permission.
251541Srgrimes *
261541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
271541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
281541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
291541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
301541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
311541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
321541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
331541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
341541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
351541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
361541Srgrimes * SUCH DAMAGE.
371541Srgrimes *
3844510Swollman *	From: @(#)kern_clock.c	8.5 (Berkeley) 1/21/94
3950477Speter * $FreeBSD: head/sys/kern/kern_timeout.c 81481 2001-08-10 21:06:59Z jhb $
401541Srgrimes */
411541Srgrimes
421541Srgrimes#include <sys/param.h>
431541Srgrimes#include <sys/systm.h>
4433392Sphk#include <sys/callout.h>
451541Srgrimes#include <sys/kernel.h>
4674914Sjhb#include <sys/lock.h>
4768840Sjhb#include <sys/mutex.h>
481541Srgrimes
4933392Sphk/*
5033392Sphk * TODO:
5133392Sphk *	allocate more timeout table slots when table overflows.
5233392Sphk */
5333392Sphk
5433392Sphk/* Exported to machdep.c and/or kern_clock.c.  */
5529680Sgibbsstruct callout *callout;
5629680Sgibbsstruct callout_list callfree;
5729680Sgibbsint callwheelsize, callwheelbits, callwheelmask;
5829680Sgibbsstruct callout_tailq *callwheel;
5933392Sphkint softticks;			/* Like ticks, but for softclock(). */
6068889Sjakestruct mtx callout_lock;
612112Swollman
6229680Sgibbsstatic struct callout *nextsoftcheck;	/* Next callout to be checked. */
631541Srgrimes
641541Srgrimes/*
6529680Sgibbs * The callout mechanism is based on the work of Adam M. Costello and
6629680Sgibbs * George Varghese, published in a technical report entitled "Redesigning
6729680Sgibbs * the BSD Callout and Timer Facilities" and modified slightly for inclusion
6829680Sgibbs * in FreeBSD by Justin T. Gibbs.  The original work on the data structures
6929680Sgibbs * used in this implementation was published by G.Varghese and A. Lauck in
7029680Sgibbs * the paper "Hashed and Hierarchical Timing Wheels: Data Structures for
7129680Sgibbs * the Efficient Implementation of a Timer Facility" in the Proceedings of
7229680Sgibbs * the 11th ACM Annual Symposium on Operating Systems Principles,
7329680Sgibbs * Austin, Texas Nov 1987.
7429680Sgibbs */
7532388Sphk
7629680Sgibbs/*
771541Srgrimes * Software (low priority) clock interrupt.
781541Srgrimes * Run periodic events from timeout queue.
791541Srgrimes */
801541Srgrimesvoid
8167551Sjhbsoftclock(void *dummy)
821541Srgrimes{
831541Srgrimes	register struct callout *c;
8429805Sgibbs	register struct callout_tailq *bucket;
8529805Sgibbs	register int curticks;
8633392Sphk	register int steps;	/* #steps since we last allowed interrupts */
871541Srgrimes
8833392Sphk#ifndef MAX_SOFTCLOCK_STEPS
8933392Sphk#define MAX_SOFTCLOCK_STEPS 100 /* Maximum allowed value of steps. */
9033392Sphk#endif /* MAX_SOFTCLOCK_STEPS */
9129680Sgibbs
9229680Sgibbs	steps = 0;
9372200Sbmilekic	mtx_lock_spin(&callout_lock);
9429680Sgibbs	while (softticks != ticks) {
9529805Sgibbs		softticks++;
9629805Sgibbs		/*
9729805Sgibbs		 * softticks may be modified by hard clock, so cache
9829805Sgibbs		 * it while we work on a given bucket.
9929805Sgibbs		 */
10029805Sgibbs		curticks = softticks;
10129805Sgibbs		bucket = &callwheel[curticks & callwheelmask];
10229805Sgibbs		c = TAILQ_FIRST(bucket);
10329680Sgibbs		while (c) {
10429805Sgibbs			if (c->c_time != curticks) {
10529680Sgibbs				c = TAILQ_NEXT(c, c_links.tqe);
10629680Sgibbs				++steps;
10729680Sgibbs				if (steps >= MAX_SOFTCLOCK_STEPS) {
10829680Sgibbs					nextsoftcheck = c;
10929805Sgibbs					/* Give interrupts a chance. */
11072200Sbmilekic					mtx_unlock_spin(&callout_lock);
11181370Sjhb					;	/* nothing */
11272200Sbmilekic					mtx_lock_spin(&callout_lock);
11329680Sgibbs					c = nextsoftcheck;
11429680Sgibbs					steps = 0;
11529680Sgibbs				}
11629680Sgibbs			} else {
11729680Sgibbs				void (*c_func)(void *);
11829680Sgibbs				void *c_arg;
11968889Sjake				int c_flags;
12029680Sgibbs
12129680Sgibbs				nextsoftcheck = TAILQ_NEXT(c, c_links.tqe);
12229805Sgibbs				TAILQ_REMOVE(bucket, c, c_links.tqe);
12329680Sgibbs				c_func = c->c_func;
12429680Sgibbs				c_arg = c->c_arg;
12568889Sjake				c_flags = c->c_flags;
12629680Sgibbs				c->c_func = NULL;
12744510Swollman				if (c->c_flags & CALLOUT_LOCAL_ALLOC) {
12844510Swollman					c->c_flags = CALLOUT_LOCAL_ALLOC;
12944510Swollman					SLIST_INSERT_HEAD(&callfree, c,
13044510Swollman							  c_links.sle);
13144510Swollman				} else {
13244510Swollman					c->c_flags =
13350673Sjlemon					    (c->c_flags & ~CALLOUT_PENDING);
13444510Swollman				}
13572200Sbmilekic				mtx_unlock_spin(&callout_lock);
13668889Sjake				if (!(c_flags & CALLOUT_MPSAFE))
13772200Sbmilekic					mtx_lock(&Giant);
13829680Sgibbs				c_func(c_arg);
13968889Sjake				if (!(c_flags & CALLOUT_MPSAFE))
14072200Sbmilekic					mtx_unlock(&Giant);
14172200Sbmilekic				mtx_lock_spin(&callout_lock);
14229680Sgibbs				steps = 0;
14329680Sgibbs				c = nextsoftcheck;
14429680Sgibbs			}
14529680Sgibbs		}
1461541Srgrimes	}
14729680Sgibbs	nextsoftcheck = NULL;
14872200Sbmilekic	mtx_unlock_spin(&callout_lock);
1491541Srgrimes}
1501541Srgrimes
1511541Srgrimes/*
1521541Srgrimes * timeout --
1531541Srgrimes *	Execute a function after a specified length of time.
1541541Srgrimes *
1551541Srgrimes * untimeout --
1561541Srgrimes *	Cancel previous timeout function call.
1571541Srgrimes *
15829680Sgibbs * callout_handle_init --
15929680Sgibbs *	Initialize a handle so that using it with untimeout is benign.
16029680Sgibbs *
1611541Srgrimes *	See AT&T BCI Driver Reference Manual for specification.  This
16229680Sgibbs *	implementation differs from that one in that although an
16329680Sgibbs *	identification value is returned from timeout, the original
16429680Sgibbs *	arguments to timeout as well as the identifier are used to
16529680Sgibbs *	identify entries for untimeout.
1661541Srgrimes */
16729680Sgibbsstruct callout_handle
16829680Sgibbstimeout(ftn, arg, to_ticks)
16933824Sbde	timeout_t *ftn;
1701541Srgrimes	void *arg;
17169147Sjlemon	int to_ticks;
1721541Srgrimes{
17329680Sgibbs	struct callout *new;
17429680Sgibbs	struct callout_handle handle;
1751541Srgrimes
17672200Sbmilekic	mtx_lock_spin(&callout_lock);
1771541Srgrimes
1781541Srgrimes	/* Fill in the next free callout structure. */
17929680Sgibbs	new = SLIST_FIRST(&callfree);
18029680Sgibbs	if (new == NULL)
18129680Sgibbs		/* XXX Attempt to malloc first */
1821541Srgrimes		panic("timeout table full");
18329680Sgibbs	SLIST_REMOVE_HEAD(&callfree, c_links.sle);
18444510Swollman
18544510Swollman	callout_reset(new, to_ticks, ftn, arg);
1861541Srgrimes
18744510Swollman	handle.callout = new;
18872200Sbmilekic	mtx_unlock_spin(&callout_lock);
18929680Sgibbs	return (handle);
1901541Srgrimes}
1911541Srgrimes
1921541Srgrimesvoid
19329680Sgibbsuntimeout(ftn, arg, handle)
19433824Sbde	timeout_t *ftn;
1951541Srgrimes	void *arg;
19629680Sgibbs	struct callout_handle handle;
1971541Srgrimes{
1981541Srgrimes
19929680Sgibbs	/*
20029680Sgibbs	 * Check for a handle that was initialized
20129680Sgibbs	 * by callout_handle_init, but never used
20229680Sgibbs	 * for a real timeout.
20329680Sgibbs	 */
20429680Sgibbs	if (handle.callout == NULL)
20529680Sgibbs		return;
20629680Sgibbs
20772200Sbmilekic	mtx_lock_spin(&callout_lock);
20844510Swollman	if (handle.callout->c_func == ftn && handle.callout->c_arg == arg)
20944510Swollman		callout_stop(handle.callout);
21072200Sbmilekic	mtx_unlock_spin(&callout_lock);
2111541Srgrimes}
2121541Srgrimes
21324101Sbdevoid
21429680Sgibbscallout_handle_init(struct callout_handle *handle)
21529680Sgibbs{
21629680Sgibbs	handle->callout = NULL;
21729680Sgibbs}
21829680Sgibbs
21944510Swollman/*
22044510Swollman * New interface; clients allocate their own callout structures.
22144510Swollman *
22244510Swollman * callout_reset() - establish or change a timeout
22344510Swollman * callout_stop() - disestablish a timeout
22444510Swollman * callout_init() - initialize a callout structure so that it can
22544510Swollman *	safely be passed to callout_reset() and callout_stop()
22644510Swollman *
22750673Sjlemon * <sys/callout.h> defines three convenience macros:
22844510Swollman *
22950673Sjlemon * callout_active() - returns truth if callout has not been serviced
23050673Sjlemon * callout_pending() - returns truth if callout is still waiting for timeout
23150673Sjlemon * callout_deactivate() - marks the callout as having been serviced
23244510Swollman */
23344510Swollmanvoid
23469147Sjlemoncallout_reset(c, to_ticks, ftn, arg)
23544510Swollman	struct	callout *c;
23644510Swollman	int	to_ticks;
23744510Swollman	void	(*ftn) __P((void *));
23844510Swollman	void	*arg;
23944510Swollman{
24044510Swollman
24172200Sbmilekic	mtx_lock_spin(&callout_lock);
24244510Swollman	if (c->c_flags & CALLOUT_PENDING)
24344510Swollman		callout_stop(c);
24444510Swollman
24544510Swollman	/*
24681370Sjhb	 * We could unlock callout_lock here and lock it again before the
24781370Sjhb	 * TAILQ_INSERT_TAIL, but there's no point since doing this setup
24881370Sjhb	 * doesn't take much time.
24944510Swollman	 */
25044510Swollman	if (to_ticks <= 0)
25144510Swollman		to_ticks = 1;
25244510Swollman
25344510Swollman	c->c_arg = arg;
25469147Sjlemon	c->c_flags |= (CALLOUT_ACTIVE | CALLOUT_PENDING);
25544510Swollman	c->c_func = ftn;
25644510Swollman	c->c_time = ticks + to_ticks;
25744510Swollman	TAILQ_INSERT_TAIL(&callwheel[c->c_time & callwheelmask],
25844510Swollman			  c, c_links.tqe);
25972200Sbmilekic	mtx_unlock_spin(&callout_lock);
26044510Swollman}
26144510Swollman
26281481Sjhbint
26344510Swollmancallout_stop(c)
26444510Swollman	struct	callout *c;
26544510Swollman{
26644510Swollman
26772200Sbmilekic	mtx_lock_spin(&callout_lock);
26844510Swollman	/*
26944510Swollman	 * Don't attempt to delete a callout that's not on the queue.
27044510Swollman	 */
27144510Swollman	if (!(c->c_flags & CALLOUT_PENDING)) {
27250673Sjlemon		c->c_flags &= ~CALLOUT_ACTIVE;
27372200Sbmilekic		mtx_unlock_spin(&callout_lock);
27481481Sjhb		return (0);
27544510Swollman	}
27650673Sjlemon	c->c_flags &= ~(CALLOUT_ACTIVE | CALLOUT_PENDING);
27744510Swollman
27844510Swollman	if (nextsoftcheck == c) {
27944510Swollman		nextsoftcheck = TAILQ_NEXT(c, c_links.tqe);
28044510Swollman	}
28144510Swollman	TAILQ_REMOVE(&callwheel[c->c_time & callwheelmask], c, c_links.tqe);
28244510Swollman	c->c_func = NULL;
28344510Swollman
28444510Swollman	if (c->c_flags & CALLOUT_LOCAL_ALLOC) {
28544510Swollman		SLIST_INSERT_HEAD(&callfree, c, c_links.sle);
28644510Swollman	}
28772200Sbmilekic	mtx_unlock_spin(&callout_lock);
28881481Sjhb	return (1);
28944510Swollman}
29044510Swollman
29144510Swollmanvoid
29269147Sjlemoncallout_init(c, mpsafe)
29344510Swollman	struct	callout *c;
29469147Sjlemon	int mpsafe;
29544510Swollman{
29644527Swollman	bzero(c, sizeof *c);
29769147Sjlemon	if (mpsafe)
29869147Sjlemon		c->c_flags |= CALLOUT_MPSAFE;
29944510Swollman}
30044510Swollman
30131950Snate#ifdef APM_FIXUP_CALLTODO
30231950Snate/*
30331950Snate * Adjust the kernel calltodo timeout list.  This routine is used after
30431950Snate * an APM resume to recalculate the calltodo timer list values with the
30531950Snate * number of hz's we have been sleeping.  The next hardclock() will detect
30631950Snate * that there are fired timers and run softclock() to execute them.
30731950Snate *
30831950Snate * Please note, I have not done an exhaustive analysis of what code this
30931950Snate * might break.  I am motivated to have my select()'s and alarm()'s that
31031950Snate * have expired during suspend firing upon resume so that the applications
31131950Snate * which set the timer can do the maintanence the timer was for as close
31231950Snate * as possible to the originally intended time.  Testing this code for a
31331950Snate * week showed that resuming from a suspend resulted in 22 to 25 timers
31431950Snate * firing, which seemed independant on whether the suspend was 2 hours or
31531950Snate * 2 days.  Your milage may vary.   - Ken Key <key@cs.utk.edu>
31631950Snate */
31731950Snatevoid
31831950Snateadjust_timeout_calltodo(time_change)
31931950Snate    struct timeval *time_change;
32031950Snate{
32131950Snate	register struct callout *p;
32231950Snate	unsigned long delta_ticks;
32331950Snate
32431950Snate	/*
32531950Snate	 * How many ticks were we asleep?
32636127Sbde	 * (stolen from tvtohz()).
32731950Snate	 */
32831950Snate
32931950Snate	/* Don't do anything */
33031950Snate	if (time_change->tv_sec < 0)
33131950Snate		return;
33231950Snate	else if (time_change->tv_sec <= LONG_MAX / 1000000)
33331950Snate		delta_ticks = (time_change->tv_sec * 1000000 +
33431950Snate			       time_change->tv_usec + (tick - 1)) / tick + 1;
33531950Snate	else if (time_change->tv_sec <= LONG_MAX / hz)
33631950Snate		delta_ticks = time_change->tv_sec * hz +
33731950Snate			      (time_change->tv_usec + (tick - 1)) / tick + 1;
33831950Snate	else
33931950Snate		delta_ticks = LONG_MAX;
34031950Snate
34131950Snate	if (delta_ticks > INT_MAX)
34231950Snate		delta_ticks = INT_MAX;
34331950Snate
34431950Snate	/*
34531950Snate	 * Now rip through the timer calltodo list looking for timers
34631950Snate	 * to expire.
34731950Snate	 */
34831950Snate
34931950Snate	/* don't collide with softclock() */
35072200Sbmilekic	mtx_lock_spin(&callout_lock);
35131950Snate	for (p = calltodo.c_next; p != NULL; p = p->c_next) {
35231950Snate		p->c_time -= delta_ticks;
35331950Snate
35431950Snate		/* Break if the timer had more time on it than delta_ticks */
35531950Snate		if (p->c_time > 0)
35631950Snate			break;
35731950Snate
35831950Snate		/* take back the ticks the timer didn't use (p->c_time <= 0) */
35931950Snate		delta_ticks = -p->c_time;
36031950Snate	}
36172200Sbmilekic	mtx_unlock_spin(&callout_lock);
36231950Snate
36331950Snate	return;
36431950Snate}
36531950Snate#endif /* APM_FIXUP_CALLTODO */
366