Home | History | Annotate | Download | only in sys
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     23 /*	  All Rights Reserved  	*/
     24 
     25 
     26 /*
     27  * Copyright (c) 1997-1998 by Sun Microsystems, Inc.
     28  * All rights reserved.
     29  */
     30 
     31 #ifndef _SYS_CALLO_H
     32 #define	_SYS_CALLO_H
     33 
     34 #pragma ident	"@(#)callo.h	1.26	07/04/26 SMI"
     35 
     36 #include <sys/t_lock.h>
     37 #include <sys/taskq.h>
     38 
     39 #ifdef	__cplusplus
     40 extern "C" {
     41 #endif
     42 
     43 typedef long	callout_id_t;		/* internal form of timeout_id_t */
     44 
     45 /*
     46  * The callout mechanism provides general-purpose event scheduling:
     47  * an arbitrary function is called in a specified amount of time.
     48  */
     49 typedef struct callout {
     50 	struct callout	*c_idnext;	/* next in ID hash, or on freelist */
     51 	struct callout	*c_idprev;	/* prev in ID hash */
     52 	struct callout	*c_lbnext;	/* next in lbolt hash */
     53 	struct callout	*c_lbprev;	/* prev in lbolt hash */
     54 	callout_id_t	c_xid;		/* extended callout ID; see below */
     55 	clock_t		c_runtime;	/* absolute run time */
     56 	void		(*c_func)(void *); /* function to call */
     57 	void		*c_arg;		/* argument to function */
     58 	kthread_id_t	c_executor;	/* thread executing callout */
     59 	kcondvar_t	c_done;		/* signal callout completion */
     60 } callout_t;
     61 
     62 /*
     63  * The extended callout ID consists of the callout ID (as returned by
     64  * timeout()) plus a bit indicating whether the callout is executing.
     65  *
     66  * The callout ID uniquely identifies a callout.  It contains a table ID,
     67  * indicating which callout table the callout belongs to, a bit indicating
     68  * whether this is a short-term or long-term callout, and a running counter.
     69  * The highest bit of the running counter is always set; this ensures that
     70  * the callout ID is always non-zero, thus eliminating the need for an
     71  * explicit wrap-around test during ID generation.
     72  *
     73  * The long-term bit exists to address the problem of callout ID collision.
     74  * This is an issue because the system typically generates a large number of
     75  * timeout() requests, which means that callout IDs eventually get recycled.
     76  * Most timeouts are very short-lived, so that ID recycling isn't a problem;
     77  * but there are a handful of timeouts which are sufficiently long-lived to
     78  * see their own IDs reused.  We use the long-term bit to partition the
     79  * ID namespace into pieces; the short-term space gets all the heavy traffic
     80  * and can wrap frequently (i.e., on the order of a day) with no ill effects;
     81  * the long-term space gets very little traffic and thus never wraps.
     82  */
     83 #define	CALLOUT_EXECUTING	(1UL << (8 * sizeof (long) - 1))
     84 #define	CALLOUT_LONGTERM	(1UL << (8 * sizeof (long) - 2))
     85 #define	CALLOUT_COUNTER_HIGH	(1UL << (8 * sizeof (long) - 3))
     86 #define	CALLOUT_FANOUT_BITS	3
     87 #define	CALLOUT_TYPE_BITS	1
     88 #define	CALLOUT_NTYPES		(1 << CALLOUT_TYPE_BITS)
     89 #define	CALLOUT_FANOUT		(1 << CALLOUT_FANOUT_BITS)
     90 #define	CALLOUT_FANOUT_MASK	(CALLOUT_FANOUT - 1)
     91 #define	CALLOUT_COUNTER_SHIFT	(CALLOUT_TYPE_BITS + CALLOUT_FANOUT_BITS)
     92 #define	CALLOUT_COUNTER_LOW	(1 << CALLOUT_COUNTER_SHIFT)
     93 #define	CALLOUT_TABLES		CALLOUT_COUNTER_LOW
     94 #define	CALLOUT_TABLE_MASK	(CALLOUT_TABLES - 1)
     95 #define	CALLOUT_TABLE(t, f)	\
     96 	(((t) << CALLOUT_FANOUT_BITS) + ((f) & CALLOUT_FANOUT_MASK))
     97 
     98 /*
     99  * We assume that during any period of CALLOUT_LONGTERM_TICKS ticks, at most
    100  * (CALLOUT_COUNTER_HIGH / CALLOUT_COUNTER_LOW) callouts will be generated.
    101  */
    102 #define	CALLOUT_LONGTERM_TICKS	0x4000
    103 #define	CALLOUT_BUCKETS		512		/* MUST be a power of 2 */
    104 #define	CALLOUT_BUCKET_MASK	(CALLOUT_BUCKETS - 1)
    105 #define	CALLOUT_HASH(x)		((x) & CALLOUT_BUCKET_MASK)
    106 #define	CALLOUT_IDHASH(x)	CALLOUT_HASH((x) >> CALLOUT_COUNTER_SHIFT)
    107 #define	CALLOUT_LBHASH(x)	CALLOUT_HASH(x)
    108 
    109 #define	CALLOUT_THREADS		2		/* keep it simple for now */
    110 
    111 #define	CALLOUT_REALTIME	0		/* realtime callout type */
    112 #define	CALLOUT_NORMAL		1		/* normal callout type */
    113 
    114 /*
    115  * All of the state information associated with a callout table.
    116  * The fields are ordered with cache performance in mind.
    117  */
    118 typedef struct callout_table {
    119 	kmutex_t	ct_lock;	/* protects all callout state */
    120 	callout_t	*ct_freelist;	/* free callout structures */
    121 	clock_t		ct_curtime;	/* current time; tracks lbolt */
    122 	clock_t		ct_runtime;	/* the callouts we're running now */
    123 	taskq_t		*ct_taskq;	/* taskq to execute normal callouts */
    124 	callout_id_t	ct_short_id;	/* most recently issued short-term ID */
    125 	callout_id_t	ct_long_id;	/* most recently issued long-term ID */
    126 	callout_t 	*ct_idhash[CALLOUT_BUCKETS];	/* ID hash chains */
    127 	callout_t 	*ct_lbhash[CALLOUT_BUCKETS];	/* lbolt hash chains */
    128 } callout_table_t;
    129 
    130 #ifdef	_KERNEL
    131 extern	void		callout_init(void);
    132 extern	void		callout_schedule(void);
    133 #endif
    134 
    135 #ifdef	__cplusplus
    136 }
    137 #endif
    138 
    139 #endif	/* _SYS_CALLO_H */
    140