xref: /titanic_53/usr/src/uts/common/sys/callo.h (revision f635d46a9872dc5a02bbbd736f2bf18685c2c221)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*f635d46aSqiao  * Common Development and Distribution License (the "License").
6*f635d46aSqiao  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
227c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
237c478bd9Sstevel@tonic-gate 
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate /*
26*f635d46aSqiao  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
27*f635d46aSqiao  * Use is subject to license terms.
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #ifndef _SYS_CALLO_H
317c478bd9Sstevel@tonic-gate #define	_SYS_CALLO_H
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #include <sys/t_lock.h>
367c478bd9Sstevel@tonic-gate #include <sys/taskq.h>
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
397c478bd9Sstevel@tonic-gate extern "C" {
407c478bd9Sstevel@tonic-gate #endif
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate typedef long	callout_id_t;		/* internal form of timeout_id_t */
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate /*
457c478bd9Sstevel@tonic-gate  * The callout mechanism provides general-purpose event scheduling:
467c478bd9Sstevel@tonic-gate  * an arbitrary function is called in a specified amount of time.
477c478bd9Sstevel@tonic-gate  */
487c478bd9Sstevel@tonic-gate typedef struct callout {
497c478bd9Sstevel@tonic-gate 	struct callout	*c_idnext;	/* next in ID hash, or on freelist */
507c478bd9Sstevel@tonic-gate 	struct callout	*c_idprev;	/* prev in ID hash */
517c478bd9Sstevel@tonic-gate 	struct callout	*c_lbnext;	/* next in lbolt hash */
527c478bd9Sstevel@tonic-gate 	struct callout	*c_lbprev;	/* prev in lbolt hash */
537c478bd9Sstevel@tonic-gate 	callout_id_t	c_xid;		/* extended callout ID; see below */
547c478bd9Sstevel@tonic-gate 	clock_t		c_runtime;	/* absolute run time */
55*f635d46aSqiao 	int64_t		c_runhrtime;	/* run time ticks since epoch */
567c478bd9Sstevel@tonic-gate 	void		(*c_func)(void *); /* function to call */
577c478bd9Sstevel@tonic-gate 	void		*c_arg;		/* argument to function */
587c478bd9Sstevel@tonic-gate 	kthread_id_t	c_executor;	/* thread executing callout */
597c478bd9Sstevel@tonic-gate 	kcondvar_t	c_done;		/* signal callout completion */
607c478bd9Sstevel@tonic-gate } callout_t;
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate /*
637c478bd9Sstevel@tonic-gate  * The extended callout ID consists of the callout ID (as returned by
647c478bd9Sstevel@tonic-gate  * timeout()) plus a bit indicating whether the callout is executing.
657c478bd9Sstevel@tonic-gate  *
667c478bd9Sstevel@tonic-gate  * The callout ID uniquely identifies a callout.  It contains a table ID,
677c478bd9Sstevel@tonic-gate  * indicating which callout table the callout belongs to, a bit indicating
687c478bd9Sstevel@tonic-gate  * whether this is a short-term or long-term callout, and a running counter.
697c478bd9Sstevel@tonic-gate  * The highest bit of the running counter is always set; this ensures that
707c478bd9Sstevel@tonic-gate  * the callout ID is always non-zero, thus eliminating the need for an
717c478bd9Sstevel@tonic-gate  * explicit wrap-around test during ID generation.
727c478bd9Sstevel@tonic-gate  *
737c478bd9Sstevel@tonic-gate  * The long-term bit exists to address the problem of callout ID collision.
747c478bd9Sstevel@tonic-gate  * This is an issue because the system typically generates a large number of
757c478bd9Sstevel@tonic-gate  * timeout() requests, which means that callout IDs eventually get recycled.
767c478bd9Sstevel@tonic-gate  * Most timeouts are very short-lived, so that ID recycling isn't a problem;
777c478bd9Sstevel@tonic-gate  * but there are a handful of timeouts which are sufficiently long-lived to
787c478bd9Sstevel@tonic-gate  * see their own IDs reused.  We use the long-term bit to partition the
797c478bd9Sstevel@tonic-gate  * ID namespace into pieces; the short-term space gets all the heavy traffic
807c478bd9Sstevel@tonic-gate  * and can wrap frequently (i.e., on the order of a day) with no ill effects;
817c478bd9Sstevel@tonic-gate  * the long-term space gets very little traffic and thus never wraps.
827c478bd9Sstevel@tonic-gate  */
837c478bd9Sstevel@tonic-gate #define	CALLOUT_EXECUTING	(1UL << (8 * sizeof (long) - 1))
847c478bd9Sstevel@tonic-gate #define	CALLOUT_LONGTERM	(1UL << (8 * sizeof (long) - 2))
857c478bd9Sstevel@tonic-gate #define	CALLOUT_COUNTER_HIGH	(1UL << (8 * sizeof (long) - 3))
867c478bd9Sstevel@tonic-gate #define	CALLOUT_FANOUT_BITS	3
877c478bd9Sstevel@tonic-gate #define	CALLOUT_TYPE_BITS	1
887c478bd9Sstevel@tonic-gate #define	CALLOUT_NTYPES		(1 << CALLOUT_TYPE_BITS)
897c478bd9Sstevel@tonic-gate #define	CALLOUT_FANOUT		(1 << CALLOUT_FANOUT_BITS)
907c478bd9Sstevel@tonic-gate #define	CALLOUT_FANOUT_MASK	(CALLOUT_FANOUT - 1)
917c478bd9Sstevel@tonic-gate #define	CALLOUT_COUNTER_SHIFT	(CALLOUT_TYPE_BITS + CALLOUT_FANOUT_BITS)
927c478bd9Sstevel@tonic-gate #define	CALLOUT_COUNTER_LOW	(1 << CALLOUT_COUNTER_SHIFT)
937c478bd9Sstevel@tonic-gate #define	CALLOUT_TABLES		CALLOUT_COUNTER_LOW
947c478bd9Sstevel@tonic-gate #define	CALLOUT_TABLE_MASK	(CALLOUT_TABLES - 1)
957c478bd9Sstevel@tonic-gate #define	CALLOUT_TABLE(t, f)	\
967c478bd9Sstevel@tonic-gate 	(((t) << CALLOUT_FANOUT_BITS) + ((f) & CALLOUT_FANOUT_MASK))
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate /*
997c478bd9Sstevel@tonic-gate  * We assume that during any period of CALLOUT_LONGTERM_TICKS ticks, at most
1007c478bd9Sstevel@tonic-gate  * (CALLOUT_COUNTER_HIGH / CALLOUT_COUNTER_LOW) callouts will be generated.
1017c478bd9Sstevel@tonic-gate  */
1027c478bd9Sstevel@tonic-gate #define	CALLOUT_LONGTERM_TICKS	0x4000
1037c478bd9Sstevel@tonic-gate #define	CALLOUT_BUCKETS		512		/* MUST be a power of 2 */
1047c478bd9Sstevel@tonic-gate #define	CALLOUT_BUCKET_MASK	(CALLOUT_BUCKETS - 1)
1057c478bd9Sstevel@tonic-gate #define	CALLOUT_HASH(x)		((x) & CALLOUT_BUCKET_MASK)
1067c478bd9Sstevel@tonic-gate #define	CALLOUT_IDHASH(x)	CALLOUT_HASH((x) >> CALLOUT_COUNTER_SHIFT)
1077c478bd9Sstevel@tonic-gate #define	CALLOUT_LBHASH(x)	CALLOUT_HASH(x)
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate #define	CALLOUT_THREADS		2		/* keep it simple for now */
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate #define	CALLOUT_REALTIME	0		/* realtime callout type */
1127c478bd9Sstevel@tonic-gate #define	CALLOUT_NORMAL		1		/* normal callout type */
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate /*
1157c478bd9Sstevel@tonic-gate  * All of the state information associated with a callout table.
1167c478bd9Sstevel@tonic-gate  * The fields are ordered with cache performance in mind.
1177c478bd9Sstevel@tonic-gate  */
1187c478bd9Sstevel@tonic-gate typedef struct callout_table {
1197c478bd9Sstevel@tonic-gate 	kmutex_t	ct_lock;	/* protects all callout state */
1207c478bd9Sstevel@tonic-gate 	callout_t	*ct_freelist;	/* free callout structures */
1217c478bd9Sstevel@tonic-gate 	clock_t		ct_curtime;	/* current time; tracks lbolt */
1227c478bd9Sstevel@tonic-gate 	clock_t		ct_runtime;	/* the callouts we're running now */
123*f635d46aSqiao 	int64_t		ct_curhrtime;	/* current time ticks since epoch */
1247c478bd9Sstevel@tonic-gate 	taskq_t		*ct_taskq;	/* taskq to execute normal callouts */
1257c478bd9Sstevel@tonic-gate 	callout_id_t	ct_short_id;	/* most recently issued short-term ID */
1267c478bd9Sstevel@tonic-gate 	callout_id_t	ct_long_id;	/* most recently issued long-term ID */
1277c478bd9Sstevel@tonic-gate 	callout_t 	*ct_idhash[CALLOUT_BUCKETS];	/* ID hash chains */
1287c478bd9Sstevel@tonic-gate 	callout_t 	*ct_lbhash[CALLOUT_BUCKETS];	/* lbolt hash chains */
1297c478bd9Sstevel@tonic-gate } callout_table_t;
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate #ifdef	_KERNEL
1327c478bd9Sstevel@tonic-gate extern	void		callout_init(void);
1337c478bd9Sstevel@tonic-gate extern	void		callout_schedule(void);
1347c478bd9Sstevel@tonic-gate #endif
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
1377c478bd9Sstevel@tonic-gate }
1387c478bd9Sstevel@tonic-gate #endif
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate #endif	/* _SYS_CALLO_H */
141