xref: /onnv-gate/usr/src/uts/common/sys/callo.h (revision 11950:27929c562084)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
56422Sqiao  * Common Development and Distribution License (the "License").
66422Sqiao  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
220Sstevel@tonic-gate /*	  All Rights Reserved  	*/
230Sstevel@tonic-gate 
240Sstevel@tonic-gate 
250Sstevel@tonic-gate /*
2611745SMadhavan.Venkataraman@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
276422Sqiao  * Use is subject to license terms.
280Sstevel@tonic-gate  */
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #ifndef _SYS_CALLO_H
310Sstevel@tonic-gate #define	_SYS_CALLO_H
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include <sys/t_lock.h>
340Sstevel@tonic-gate #include <sys/taskq.h>
358048SMadhavan.Venkataraman@Sun.COM #include <sys/lgrp.h>
368048SMadhavan.Venkataraman@Sun.COM #include <sys/processor.h>
378048SMadhavan.Venkataraman@Sun.COM #include <sys/cyclic.h>
388048SMadhavan.Venkataraman@Sun.COM #include <sys/kstat.h>
398048SMadhavan.Venkataraman@Sun.COM #include <sys/systm.h>
400Sstevel@tonic-gate 
410Sstevel@tonic-gate #ifdef	__cplusplus
420Sstevel@tonic-gate extern "C" {
430Sstevel@tonic-gate #endif
440Sstevel@tonic-gate 
458048SMadhavan.Venkataraman@Sun.COM #ifdef	_KERNEL
468048SMadhavan.Venkataraman@Sun.COM 
478048SMadhavan.Venkataraman@Sun.COM typedef struct callout_list	callout_list_t;
480Sstevel@tonic-gate 
490Sstevel@tonic-gate /*
500Sstevel@tonic-gate  * The callout mechanism provides general-purpose event scheduling:
510Sstevel@tonic-gate  * an arbitrary function is called in a specified amount of time.
528048SMadhavan.Venkataraman@Sun.COM  * The expiration time for a callout is kept in its callout list
538048SMadhavan.Venkataraman@Sun.COM  * structure.
540Sstevel@tonic-gate  */
550Sstevel@tonic-gate typedef struct callout {
560Sstevel@tonic-gate 	struct callout	*c_idnext;	/* next in ID hash, or on freelist */
570Sstevel@tonic-gate 	struct callout	*c_idprev;	/* prev in ID hash */
588048SMadhavan.Venkataraman@Sun.COM 	struct callout	*c_clnext;	/* next in callout list */
598048SMadhavan.Venkataraman@Sun.COM 	struct callout	*c_clprev;	/* prev in callout list */
600Sstevel@tonic-gate 	callout_id_t	c_xid;		/* extended callout ID; see below */
618048SMadhavan.Venkataraman@Sun.COM 	callout_list_t	*c_list;	/* callout list */
620Sstevel@tonic-gate 	void		(*c_func)(void *); /* function to call */
630Sstevel@tonic-gate 	void		*c_arg;		/* argument to function */
649039SMadhavan.Venkataraman@Sun.COM 	kthread_t	*c_executor;	/* executing thread */
659039SMadhavan.Venkataraman@Sun.COM 	kcondvar_t	c_done;		/* signal callout completion */
669039SMadhavan.Venkataraman@Sun.COM 	ushort_t	c_waiting;	/* untimeout waiting flag */
670Sstevel@tonic-gate } callout_t;
680Sstevel@tonic-gate 
690Sstevel@tonic-gate /*
708048SMadhavan.Venkataraman@Sun.COM  * The callout ID (callout_id_t) uniquely identifies a callout. The callout
718048SMadhavan.Venkataraman@Sun.COM  * ID is always 64 bits internally. The lower 32 bits contain an ID value.
728048SMadhavan.Venkataraman@Sun.COM  * The upper 32 bits contain a generation number and flags. When the ID value
738048SMadhavan.Venkataraman@Sun.COM  * wraps the generation number is incremented during ID generation. This
748048SMadhavan.Venkataraman@Sun.COM  * protects callers from ID collisions that can happen as a result of the wrap.
758048SMadhavan.Venkataraman@Sun.COM  *
768048SMadhavan.Venkataraman@Sun.COM  * The kernel internal interface, timeout_generic(), always returns a
778048SMadhavan.Venkataraman@Sun.COM  * callout_id_t. But the legacy interfaces, timeout() and realtime_timeout()
788048SMadhavan.Venkataraman@Sun.COM  * return a timeout_id_t. On a 64-bit system, timeout_id_t is also 64 bits.
798048SMadhavan.Venkataraman@Sun.COM  * So, the full 64-bit ID (sans the flags) can be returned. However, on 32-bit
808048SMadhavan.Venkataraman@Sun.COM  * systems, timeout_id_t is 32 bits. So, only the lower 32 bits can be
818048SMadhavan.Venkataraman@Sun.COM  * returned. In such cases, a default generation number of 0 is assigned to
828048SMadhavan.Venkataraman@Sun.COM  * the legacy IDs.
838048SMadhavan.Venkataraman@Sun.COM  *
849334SMadhavan.Venkataraman@Sun.COM  * The lower 32-bit ID space is partitioned into two spaces - one for
859334SMadhavan.Venkataraman@Sun.COM  * short-term callouts and one for long-term.
868048SMadhavan.Venkataraman@Sun.COM  *
878048SMadhavan.Venkataraman@Sun.COM  * Here is the bit layout for the callout ID:
880Sstevel@tonic-gate  *
899334SMadhavan.Venkataraman@Sun.COM  *      63    62    61 ...  32    31      30     29 .. X+1  X ... 1   0
909334SMadhavan.Venkataraman@Sun.COM  *  -----------------------------------------------------------------------
919334SMadhavan.Venkataraman@Sun.COM  *  | Free | Exec | Generation | Long | Counter | ID bits | Table  | Type |
929334SMadhavan.Venkataraman@Sun.COM  *  |      |      | number     | term | High    |         | number |      |
939334SMadhavan.Venkataraman@Sun.COM  *  -----------------------------------------------------------------------
949334SMadhavan.Venkataraman@Sun.COM  *
959334SMadhavan.Venkataraman@Sun.COM  * Free:
969334SMadhavan.Venkataraman@Sun.COM  *    This bit indicates that this callout has been freed. This is for
979334SMadhavan.Venkataraman@Sun.COM  *    debugging purposes.
988048SMadhavan.Venkataraman@Sun.COM  *
998048SMadhavan.Venkataraman@Sun.COM  * Exec(uting):
1008048SMadhavan.Venkataraman@Sun.COM  *    This is the executing bit which is only set in the extended callout
1018048SMadhavan.Venkataraman@Sun.COM  *    ID. This bit indicates that the callout handler is currently being
1028048SMadhavan.Venkataraman@Sun.COM  *    executed.
1038048SMadhavan.Venkataraman@Sun.COM  *
1048048SMadhavan.Venkataraman@Sun.COM  * Generation number:
1058048SMadhavan.Venkataraman@Sun.COM  *    This is the generation part of the ID.
1068048SMadhavan.Venkataraman@Sun.COM  *
1078048SMadhavan.Venkataraman@Sun.COM  * Long term:
1088048SMadhavan.Venkataraman@Sun.COM  *    This bit indicates whether this is a short-term or a long-term callout.
1098048SMadhavan.Venkataraman@Sun.COM  *    The long-term bit exists to address the problem of callout ID collision
1108048SMadhavan.Venkataraman@Sun.COM  *    on 32-bit systems. This is an issue because the system typically
1118048SMadhavan.Venkataraman@Sun.COM  *    generates a large number of timeout() requests, which means that callout
1128048SMadhavan.Venkataraman@Sun.COM  *    IDs eventually get recycled. Most timeouts are very short-lived, so that
1138048SMadhavan.Venkataraman@Sun.COM  *    ID recycling isn't a problem; but there are a handful of timeouts which
1148048SMadhavan.Venkataraman@Sun.COM  *    are sufficiently long-lived to see their own IDs reused. We use the
1158048SMadhavan.Venkataraman@Sun.COM  *    long-term bit to partition the ID namespace into pieces; the short-term
1168048SMadhavan.Venkataraman@Sun.COM  *    space gets all the heavy traffic and can wrap frequently (i.e., on the
1178048SMadhavan.Venkataraman@Sun.COM  *    order of a day) with no ill effects; the long-term space gets very little
1188048SMadhavan.Venkataraman@Sun.COM  *    traffic and thus never wraps. That said, we need to future proof callouts
1198048SMadhavan.Venkataraman@Sun.COM  *    in case 32-bit systems grow in size and are able to consume callout IDs
1208048SMadhavan.Venkataraman@Sun.COM  *    at faster rates. So, we should make all the kernel clients that use
1218048SMadhavan.Venkataraman@Sun.COM  *    callouts to use the internal interface so that they can use IDs outside
1228048SMadhavan.Venkataraman@Sun.COM  *    of the legacy space with a proper generation number.
1238048SMadhavan.Venkataraman@Sun.COM  *
1248048SMadhavan.Venkataraman@Sun.COM  * Counter High + ID counter bits:
1258048SMadhavan.Venkataraman@Sun.COM  *    These bits represent the actual ID bits in the callout ID.
1268048SMadhavan.Venkataraman@Sun.COM  *    The highest bit of the running counter is always set; this ensures that
1278048SMadhavan.Venkataraman@Sun.COM  *    the callout ID is always non-zero, thus eliminating the need for an
1288048SMadhavan.Venkataraman@Sun.COM  *    explicit wrap-around test during ID generation.
1298048SMadhavan.Venkataraman@Sun.COM  *
1308048SMadhavan.Venkataraman@Sun.COM  * Table number:
1318048SMadhavan.Venkataraman@Sun.COM  *    These bits carry the table number for the callout table where the callout
1328048SMadhavan.Venkataraman@Sun.COM  *    is queued. Each CPU has its own callout table. So, the callout tables are
1338048SMadhavan.Venkataraman@Sun.COM  *    numbered from 0 - (max_ncpus - 1). Because max_ncpus is different on
1348048SMadhavan.Venkataraman@Sun.COM  *    different systems, the actual number of table number bits will vary
1358048SMadhavan.Venkataraman@Sun.COM  *    accordingly. And so will the ID counter bits.
1368048SMadhavan.Venkataraman@Sun.COM  *
1378048SMadhavan.Venkataraman@Sun.COM  * Type:
1388048SMadhavan.Venkataraman@Sun.COM  *    This bit represents the callout (table) type. Each CPU has one realtime
1398048SMadhavan.Venkataraman@Sun.COM  *    and one normal callout table.
1400Sstevel@tonic-gate  */
14111745SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_ID_FREE		0x8000000000000000ULL
1429334SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_EXECUTING	0x4000000000000000ULL
14311745SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_ID_FLAGS	(CALLOUT_ID_FREE | CALLOUT_EXECUTING)
1449334SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_ID_MASK		~CALLOUT_ID_FLAGS
1458048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_GENERATION_LOW	0x100000000ULL
1468048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_LONGTERM	0x80000000
1478048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_COUNTER_HIGH	0x40000000
1480Sstevel@tonic-gate #define	CALLOUT_TYPE_BITS	1
1490Sstevel@tonic-gate #define	CALLOUT_NTYPES		(1 << CALLOUT_TYPE_BITS)
1508048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_TYPE_MASK	(CALLOUT_NTYPES - 1)
1518048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_COUNTER_SHIFT	callout_table_bits
1528048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_TABLE(t, f)	(((f) << CALLOUT_TYPE_BITS) | (t))
1538048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_TABLE_NUM(ct)	((ct) - callout_table)
1548048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_TABLE_SEQID(ct)	(CALLOUT_TABLE_NUM(ct) >> CALLOUT_TYPE_BITS)
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate /*
1570Sstevel@tonic-gate  * We assume that during any period of CALLOUT_LONGTERM_TICKS ticks, at most
1588048SMadhavan.Venkataraman@Sun.COM  * (CALLOUT_COUNTER_HIGH / callout_counter_low) callouts will be generated.
1590Sstevel@tonic-gate  */
1608048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_LONGTERM_TICKS	0x4000UL
1618048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_BUCKET_SHIFT	9
1628048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_BUCKETS		(1 << CALLOUT_BUCKET_SHIFT)
1630Sstevel@tonic-gate #define	CALLOUT_BUCKET_MASK	(CALLOUT_BUCKETS - 1)
1640Sstevel@tonic-gate #define	CALLOUT_HASH(x)		((x) & CALLOUT_BUCKET_MASK)
1650Sstevel@tonic-gate #define	CALLOUT_IDHASH(x)	CALLOUT_HASH((x) >> CALLOUT_COUNTER_SHIFT)
1668048SMadhavan.Venkataraman@Sun.COM /*
1678048SMadhavan.Venkataraman@Sun.COM  * The multiply by 0 and 1 below are cosmetic. Just to align things better
1688048SMadhavan.Venkataraman@Sun.COM  * and make it more readable. The multiplications will be done at compile
1698048SMadhavan.Venkataraman@Sun.COM  * time.
1708048SMadhavan.Venkataraman@Sun.COM  */
1718048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_CLHASH(x)			\
1728048SMadhavan.Venkataraman@Sun.COM 	CALLOUT_HASH(				\
1738048SMadhavan.Venkataraman@Sun.COM 	    ((x)>>(CALLOUT_BUCKET_SHIFT*0)) ^	\
1748048SMadhavan.Venkataraman@Sun.COM 	    ((x)>>(CALLOUT_BUCKET_SHIFT*1)) ^	\
1758048SMadhavan.Venkataraman@Sun.COM 	    ((x)>>(CALLOUT_BUCKET_SHIFT*2)) ^	\
1768048SMadhavan.Venkataraman@Sun.COM 	    ((x)>>(CALLOUT_BUCKET_SHIFT*3)))
1778048SMadhavan.Venkataraman@Sun.COM 
1788048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_ID_TO_TABLE(id)		((id) & callout_table_mask)
1798048SMadhavan.Venkataraman@Sun.COM 
1808048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_SHORT_ID(table)		\
1818048SMadhavan.Venkataraman@Sun.COM 		((callout_id_t)(table) | CALLOUT_COUNTER_HIGH)
1828048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_LONG_ID(table)		\
1838048SMadhavan.Venkataraman@Sun.COM 		(CALLOUT_SHORT_ID(table) | CALLOUT_LONGTERM)
1840Sstevel@tonic-gate 
1859334SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_THREADS		2
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate #define	CALLOUT_REALTIME	0		/* realtime callout type */
1880Sstevel@tonic-gate #define	CALLOUT_NORMAL		1		/* normal callout type */
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate /*
1918048SMadhavan.Venkataraman@Sun.COM  * callout_t's are cache-aligned structures allocated from kmem caches. One kmem
1928048SMadhavan.Venkataraman@Sun.COM  * cache is created per lgrp and is shared by all CPUs in that lgrp. Benefits:
1938048SMadhavan.Venkataraman@Sun.COM  *	- cache pages are mapped only in the TLBs of the CPUs of the lgrp
1948048SMadhavan.Venkataraman@Sun.COM  *	- data in cache pages is present only in those CPU caches
1958048SMadhavan.Venkataraman@Sun.COM  *	- memory access performance improves with locality-awareness in kmem
1968048SMadhavan.Venkataraman@Sun.COM  *
1978048SMadhavan.Venkataraman@Sun.COM  * The following structure is used to manage per-lgroup kmem caches.
1988048SMadhavan.Venkataraman@Sun.COM  *
1998048SMadhavan.Venkataraman@Sun.COM  * NOTE: Free callout_t's go to a callout table's freelist. CPUs map to callout
2008048SMadhavan.Venkataraman@Sun.COM  * tables via their sequence IDs, not CPU IDs. DR operations can cause a
2018048SMadhavan.Venkataraman@Sun.COM  * free list to have callouts from multiple lgrp caches. This takes away some
2028048SMadhavan.Venkataraman@Sun.COM  * performance, but is no worse than if we did not use lgrp caches at all.
2038048SMadhavan.Venkataraman@Sun.COM  */
2048048SMadhavan.Venkataraman@Sun.COM typedef struct callout_cache {
2058048SMadhavan.Venkataraman@Sun.COM 	struct callout_cache	*cc_next;	/* link in the global list */
2068048SMadhavan.Venkataraman@Sun.COM 	lgrp_handle_t		cc_hand;	/* lgroup handle */
2078048SMadhavan.Venkataraman@Sun.COM 	kmem_cache_t		*cc_cache;	/* kmem cache pointer */
2088048SMadhavan.Venkataraman@Sun.COM 	kmem_cache_t		*cc_lcache;	/* kmem cache pointer */
2098048SMadhavan.Venkataraman@Sun.COM } callout_cache_t;
2108048SMadhavan.Venkataraman@Sun.COM 
2118048SMadhavan.Venkataraman@Sun.COM /*
2128048SMadhavan.Venkataraman@Sun.COM  * The callout hash structure is used for queueing both callouts and
2138048SMadhavan.Venkataraman@Sun.COM  * callout lists. That is why the fields are declared as void *.
2148048SMadhavan.Venkataraman@Sun.COM  */
2158048SMadhavan.Venkataraman@Sun.COM typedef struct callout_hash {
2168048SMadhavan.Venkataraman@Sun.COM 	void	*ch_head;
2178048SMadhavan.Venkataraman@Sun.COM 	void	*ch_tail;
2188048SMadhavan.Venkataraman@Sun.COM } callout_hash_t;
2198048SMadhavan.Venkataraman@Sun.COM 
2209334SMadhavan.Venkataraman@Sun.COM /*
2219334SMadhavan.Venkataraman@Sun.COM  * CALLOUT_LIST_FLAG_FREE
2229334SMadhavan.Venkataraman@Sun.COM  *	Callout list is free.
2239334SMadhavan.Venkataraman@Sun.COM  * CALLOUT_LIST_FLAG_ABSOLUTE
2249334SMadhavan.Venkataraman@Sun.COM  *	Callout list contains absolute timers.
2259334SMadhavan.Venkataraman@Sun.COM  * CALLOUT_LIST_FLAG_HRESTIME
2269334SMadhavan.Venkataraman@Sun.COM  *	Callout list contains hrestime timers.
2279334SMadhavan.Venkataraman@Sun.COM  * CALLOUT_LIST_FLAG_NANO
2289334SMadhavan.Venkataraman@Sun.COM  *	Callout list contains 1-nanosecond resolution callouts.
22911745SMadhavan.Venkataraman@Sun.COM  * CALLOUT_LIST_FLAG_HEAPED
23011745SMadhavan.Venkataraman@Sun.COM  *	Callout list is present in the callout heap.
23111745SMadhavan.Venkataraman@Sun.COM  * CALLOUT_LIST_FLAG_QUEUED
23211745SMadhavan.Venkataraman@Sun.COM  *	Callout list is present in the callout queue.
2339334SMadhavan.Venkataraman@Sun.COM  */
2349334SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_LIST_FLAG_FREE			0x1
2359334SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_LIST_FLAG_ABSOLUTE		0x2
2369334SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_LIST_FLAG_HRESTIME		0x4
2379334SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_LIST_FLAG_NANO			0x8
23811745SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_LIST_FLAG_HEAPED		0x10
23911745SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_LIST_FLAG_QUEUED		0x20
2409334SMadhavan.Venkataraman@Sun.COM 
2418048SMadhavan.Venkataraman@Sun.COM struct callout_list {
2428048SMadhavan.Venkataraman@Sun.COM 	callout_list_t	*cl_next;	/* next in clhash */
2438048SMadhavan.Venkataraman@Sun.COM 	callout_list_t	*cl_prev;	/* prev in clhash */
2448048SMadhavan.Venkataraman@Sun.COM 	hrtime_t	cl_expiration;	/* expiration for callouts in list */
2458048SMadhavan.Venkataraman@Sun.COM 	callout_hash_t	cl_callouts;	/* list of callouts */
2469039SMadhavan.Venkataraman@Sun.COM 	int		cl_flags;	/* callout flags */
2478048SMadhavan.Venkataraman@Sun.COM };
2488048SMadhavan.Venkataraman@Sun.COM 
2498048SMadhavan.Venkataraman@Sun.COM /*
2509334SMadhavan.Venkataraman@Sun.COM  * Callout heap element. Each element in the heap stores the expiration
2519334SMadhavan.Venkataraman@Sun.COM  * as well as the corresponding callout list. This is to avoid a lookup
2529334SMadhavan.Venkataraman@Sun.COM  * of the callout list when the heap is processed. Because we store the
2539334SMadhavan.Venkataraman@Sun.COM  * callout list pointer in the heap element, we have to always remove
2549334SMadhavan.Venkataraman@Sun.COM  * a heap element and its callout list together. We cannot remove one
2559334SMadhavan.Venkataraman@Sun.COM  * without the other.
25611745SMadhavan.Venkataraman@Sun.COM  *
25711745SMadhavan.Venkataraman@Sun.COM  * This structure's size must be a power of two because we want an
25811745SMadhavan.Venkataraman@Sun.COM  * integral number of these to fit into a page.
2599334SMadhavan.Venkataraman@Sun.COM  */
2609334SMadhavan.Venkataraman@Sun.COM typedef struct callout_heap {
2619334SMadhavan.Venkataraman@Sun.COM 	hrtime_t	ch_expiration;
2629334SMadhavan.Venkataraman@Sun.COM 	callout_list_t	*ch_list;
263*11950SMadhavan.Venkataraman@Sun.COM #ifndef _LP64
264*11950SMadhavan.Venkataraman@Sun.COM 	char		ch_pad[4];	/* pad to power of 2 */
265*11950SMadhavan.Venkataraman@Sun.COM #endif
2669334SMadhavan.Venkataraman@Sun.COM } callout_heap_t;
2679334SMadhavan.Venkataraman@Sun.COM 
2689334SMadhavan.Venkataraman@Sun.COM /*
2699334SMadhavan.Venkataraman@Sun.COM  * When the heap contains too many empty callout lists, it needs to be
2709334SMadhavan.Venkataraman@Sun.COM  * cleaned up. The decision to clean up the heap is a function of the
2719334SMadhavan.Venkataraman@Sun.COM  * number of empty entries and the heap size. Also, we don't want to
2729334SMadhavan.Venkataraman@Sun.COM  * clean up small heaps.
2739334SMadhavan.Venkataraman@Sun.COM  */
2749334SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_MIN_REAP	(CALLOUT_BUCKETS >> 3)
2759334SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_CLEANUP(ct)	((ct->ct_nreap >= callout_min_reap) &&	\
2769334SMadhavan.Venkataraman@Sun.COM 				    (ct->ct_nreap >= (ct->ct_heap_num >> 1)))
2779334SMadhavan.Venkataraman@Sun.COM 
2789334SMadhavan.Venkataraman@Sun.COM /*
2798048SMadhavan.Venkataraman@Sun.COM  * Per-callout table kstats.
2808048SMadhavan.Venkataraman@Sun.COM  *
2818048SMadhavan.Venkataraman@Sun.COM  * CALLOUT_TIMEOUTS
2828048SMadhavan.Venkataraman@Sun.COM  *	Callouts created since boot.
2838048SMadhavan.Venkataraman@Sun.COM  * CALLOUT_TIMEOUTS_PENDING
2848048SMadhavan.Venkataraman@Sun.COM  *	Number of outstanding callouts.
2858048SMadhavan.Venkataraman@Sun.COM  * CALLOUT_UNTIMEOUTS_UNEXPIRED
2868048SMadhavan.Venkataraman@Sun.COM  *	Number of cancelled callouts that have not expired.
2878048SMadhavan.Venkataraman@Sun.COM  * CALLOUT_UNTIMEOUTS_EXECUTING
2888048SMadhavan.Venkataraman@Sun.COM  *	Number of cancelled callouts that were executing at the time of
2898048SMadhavan.Venkataraman@Sun.COM  *	cancellation.
2908048SMadhavan.Venkataraman@Sun.COM  * CALLOUT_UNTIMEOUTS_EXPIRED
2918048SMadhavan.Venkataraman@Sun.COM  *	Number of cancelled callouts that had already expired at the time
2928048SMadhavan.Venkataraman@Sun.COM  *	of cancellations.
2938048SMadhavan.Venkataraman@Sun.COM  * CALLOUT_EXPIRATIONS
2948048SMadhavan.Venkataraman@Sun.COM  *	Number of callouts that expired.
2958048SMadhavan.Venkataraman@Sun.COM  * CALLOUT_ALLOCATIONS
2968048SMadhavan.Venkataraman@Sun.COM  *	Number of callout structures allocated.
2979334SMadhavan.Venkataraman@Sun.COM  * CALLOUT_CLEANUPS
2989334SMadhavan.Venkataraman@Sun.COM  *	Number of times a callout table is cleaned up.
2998048SMadhavan.Venkataraman@Sun.COM  */
3008048SMadhavan.Venkataraman@Sun.COM typedef enum callout_stat_type {
3018048SMadhavan.Venkataraman@Sun.COM 	CALLOUT_TIMEOUTS,
3028048SMadhavan.Venkataraman@Sun.COM 	CALLOUT_TIMEOUTS_PENDING,
3038048SMadhavan.Venkataraman@Sun.COM 	CALLOUT_UNTIMEOUTS_UNEXPIRED,
3048048SMadhavan.Venkataraman@Sun.COM 	CALLOUT_UNTIMEOUTS_EXECUTING,
3058048SMadhavan.Venkataraman@Sun.COM 	CALLOUT_UNTIMEOUTS_EXPIRED,
3068048SMadhavan.Venkataraman@Sun.COM 	CALLOUT_EXPIRATIONS,
3078048SMadhavan.Venkataraman@Sun.COM 	CALLOUT_ALLOCATIONS,
3089334SMadhavan.Venkataraman@Sun.COM 	CALLOUT_CLEANUPS,
3098048SMadhavan.Venkataraman@Sun.COM 	CALLOUT_NUM_STATS
3108048SMadhavan.Venkataraman@Sun.COM } callout_stat_type_t;
3118048SMadhavan.Venkataraman@Sun.COM 
3128048SMadhavan.Venkataraman@Sun.COM /*
3138048SMadhavan.Venkataraman@Sun.COM  * Callout flags:
3148048SMadhavan.Venkataraman@Sun.COM  *
3158048SMadhavan.Venkataraman@Sun.COM  * CALLOUT_FLAG_ROUNDUP
3169039SMadhavan.Venkataraman@Sun.COM  *	Roundup the expiration time to the next resolution boundary.
3178048SMadhavan.Venkataraman@Sun.COM  *	If this flag is not specified, the expiration time is rounded down.
3188048SMadhavan.Venkataraman@Sun.COM  * CALLOUT_FLAG_ABSOLUTE
3198048SMadhavan.Venkataraman@Sun.COM  *	Normally, the expiration passed to the timeout API functions is an
3208048SMadhavan.Venkataraman@Sun.COM  *	expiration interval. If this flag is specified, then it is
3218048SMadhavan.Venkataraman@Sun.COM  *	interpreted as the expiration time itself.
3228048SMadhavan.Venkataraman@Sun.COM  * CALLOUT_FLAG_HRESTIME
3238048SMadhavan.Venkataraman@Sun.COM  *	Normally, callouts are not affected by changes to system time
3248048SMadhavan.Venkataraman@Sun.COM  *	(hrestime). This flag is used to create a callout that is affected
3259039SMadhavan.Venkataraman@Sun.COM  *	by system time. If system time changes, these timers must be
3269039SMadhavan.Venkataraman@Sun.COM  *	handled in a special way (see callout.c). These are used by condition
3279039SMadhavan.Venkataraman@Sun.COM  *	variables and LWP timers that need this behavior.
3288048SMadhavan.Venkataraman@Sun.COM  * CALLOUT_FLAG_32BIT
3298048SMadhavan.Venkataraman@Sun.COM  *	Legacy interfaces timeout() and realtime_timeout() pass this flag
3308048SMadhavan.Venkataraman@Sun.COM  *	to timeout_generic() to indicate that a 32-bit ID should be allocated.
3318048SMadhavan.Venkataraman@Sun.COM  */
3328048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_FLAG_ROUNDUP		0x1
3338048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_FLAG_ABSOLUTE		0x2
3348048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_FLAG_HRESTIME		0x4
3358048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_FLAG_32BIT		0x8
3368048SMadhavan.Venkataraman@Sun.COM 
3378048SMadhavan.Venkataraman@Sun.COM /*
3388048SMadhavan.Venkataraman@Sun.COM  * On 32-bit systems, the legacy interfaces, timeout() and realtime_timeout(),
3398048SMadhavan.Venkataraman@Sun.COM  * must pass CALLOUT_FLAG_32BIT to timeout_generic() so that a 32-bit ID
3408048SMadhavan.Venkataraman@Sun.COM  * can be generated.
3418048SMadhavan.Venkataraman@Sun.COM  */
3428048SMadhavan.Venkataraman@Sun.COM #ifdef _LP64
3438048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_LEGACY		0
3448048SMadhavan.Venkataraman@Sun.COM #else
3458048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_LEGACY		CALLOUT_FLAG_32BIT
3468048SMadhavan.Venkataraman@Sun.COM #endif
3478048SMadhavan.Venkataraman@Sun.COM 
3488048SMadhavan.Venkataraman@Sun.COM /*
3490Sstevel@tonic-gate  * All of the state information associated with a callout table.
3500Sstevel@tonic-gate  * The fields are ordered with cache performance in mind.
3510Sstevel@tonic-gate  */
3520Sstevel@tonic-gate typedef struct callout_table {
3538048SMadhavan.Venkataraman@Sun.COM 	kmutex_t	ct_mutex;	/* protects all callout state */
3548048SMadhavan.Venkataraman@Sun.COM 	callout_t	*ct_free;	/* free callout structures */
3558048SMadhavan.Venkataraman@Sun.COM 	callout_list_t	*ct_lfree;	/* free callout list structures */
3560Sstevel@tonic-gate 	callout_id_t	ct_short_id;	/* most recently issued short-term ID */
3570Sstevel@tonic-gate 	callout_id_t	ct_long_id;	/* most recently issued long-term ID */
3588048SMadhavan.Venkataraman@Sun.COM 	callout_hash_t 	*ct_idhash;	/* ID hash chains */
3598048SMadhavan.Venkataraman@Sun.COM 	callout_hash_t 	*ct_clhash;	/* callout list hash */
3608048SMadhavan.Venkataraman@Sun.COM 	kstat_named_t	*ct_kstat_data;	/* callout kstat data */
3618048SMadhavan.Venkataraman@Sun.COM 
3628566SMadhavan.Venkataraman@Sun.COM 	uint_t		ct_type;	/* callout table type */
3638566SMadhavan.Venkataraman@Sun.COM 	uint_t		ct_suspend;	/* suspend count */
3648048SMadhavan.Venkataraman@Sun.COM 	cyclic_id_t	ct_cyclic;	/* cyclic for this table */
3659334SMadhavan.Venkataraman@Sun.COM 	callout_heap_t	*ct_heap;	/* callout expiration heap */
3668048SMadhavan.Venkataraman@Sun.COM 	ulong_t		ct_heap_num;	/* occupied slots in the heap */
3678048SMadhavan.Venkataraman@Sun.COM 	ulong_t		ct_heap_max;	/* end of the heap */
3688048SMadhavan.Venkataraman@Sun.COM 	kmem_cache_t	*ct_cache;	/* callout kmem cache */
3698048SMadhavan.Venkataraman@Sun.COM 	kmem_cache_t	*ct_lcache;	/* callout list kmem cache */
3708048SMadhavan.Venkataraman@Sun.COM 	callout_id_t	ct_gen_id;	/* generation based ID */
3718048SMadhavan.Venkataraman@Sun.COM 
3728048SMadhavan.Venkataraman@Sun.COM 	callout_hash_t	ct_expired;	/* list of expired callout lists */
3738048SMadhavan.Venkataraman@Sun.COM 	taskq_t		*ct_taskq;	/* taskq to execute normal callouts */
3748048SMadhavan.Venkataraman@Sun.COM 	kstat_t		*ct_kstats;	/* callout kstats */
3759334SMadhavan.Venkataraman@Sun.COM 	int		ct_nreap;	/* # heap entries that need reaping */
37611745SMadhavan.Venkataraman@Sun.COM 	cyclic_id_t	ct_qcyclic;	/* cyclic for the callout queue */
37711745SMadhavan.Venkataraman@Sun.COM 	callout_hash_t	ct_queue;	/* overflow queue of callouts */
37811745SMadhavan.Venkataraman@Sun.COM #ifndef _LP64
37911745SMadhavan.Venkataraman@Sun.COM 	char		ct_pad[12];	/* cache alignment */
3808048SMadhavan.Venkataraman@Sun.COM #endif
38111745SMadhavan.Venkataraman@Sun.COM 	/*
38211745SMadhavan.Venkataraman@Sun.COM 	 * This structure should be aligned to a 64-byte (cache-line)
38311745SMadhavan.Venkataraman@Sun.COM 	 * boundary. Make sure the padding is right for 32-bit as well
38411745SMadhavan.Venkataraman@Sun.COM 	 * as 64-bit kernels.
38511745SMadhavan.Venkataraman@Sun.COM 	 */
3860Sstevel@tonic-gate } callout_table_t;
3870Sstevel@tonic-gate 
3888048SMadhavan.Venkataraman@Sun.COM /*
3898048SMadhavan.Venkataraman@Sun.COM  * Short hand definitions for the callout kstats.
3908048SMadhavan.Venkataraman@Sun.COM  */
3918048SMadhavan.Venkataraman@Sun.COM #define	ct_timeouts							\
3928048SMadhavan.Venkataraman@Sun.COM 		ct_kstat_data[CALLOUT_TIMEOUTS].value.ui64
3938048SMadhavan.Venkataraman@Sun.COM #define	ct_timeouts_pending						\
3948048SMadhavan.Venkataraman@Sun.COM 		ct_kstat_data[CALLOUT_TIMEOUTS_PENDING].value.ui64
3958048SMadhavan.Venkataraman@Sun.COM #define	ct_untimeouts_unexpired						\
3968048SMadhavan.Venkataraman@Sun.COM 		ct_kstat_data[CALLOUT_UNTIMEOUTS_UNEXPIRED].value.ui64
3978048SMadhavan.Venkataraman@Sun.COM #define	ct_untimeouts_executing						\
3988048SMadhavan.Venkataraman@Sun.COM 		ct_kstat_data[CALLOUT_UNTIMEOUTS_EXECUTING].value.ui64
3998048SMadhavan.Venkataraman@Sun.COM #define	ct_untimeouts_expired						\
4008048SMadhavan.Venkataraman@Sun.COM 		ct_kstat_data[CALLOUT_UNTIMEOUTS_EXPIRED].value.ui64
4018048SMadhavan.Venkataraman@Sun.COM #define	ct_expirations							\
4028048SMadhavan.Venkataraman@Sun.COM 		ct_kstat_data[CALLOUT_EXPIRATIONS].value.ui64
4038048SMadhavan.Venkataraman@Sun.COM #define	ct_allocations							\
4048048SMadhavan.Venkataraman@Sun.COM 		ct_kstat_data[CALLOUT_ALLOCATIONS].value.ui64
4059334SMadhavan.Venkataraman@Sun.COM #define	ct_cleanups							\
4069334SMadhavan.Venkataraman@Sun.COM 		ct_kstat_data[CALLOUT_CLEANUPS].value.ui64
4078048SMadhavan.Venkataraman@Sun.COM 
40811745SMadhavan.Venkataraman@Sun.COM /*
40911745SMadhavan.Venkataraman@Sun.COM  * CALLOUT_CHUNK is the minimum initial size of each heap, and the amount
41011745SMadhavan.Venkataraman@Sun.COM  * by which a full heap is expanded to make room for new entries.
41111745SMadhavan.Venkataraman@Sun.COM  */
41211745SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_CHUNK		(PAGESIZE / sizeof (callout_heap_t))
41311745SMadhavan.Venkataraman@Sun.COM 
41411745SMadhavan.Venkataraman@Sun.COM /*
41511745SMadhavan.Venkataraman@Sun.COM  * CALLOUT_MIN_HEAP_SIZE defines the minimum size for the callout heap for
41611745SMadhavan.Venkataraman@Sun.COM  * the whole system.
41711745SMadhavan.Venkataraman@Sun.COM  */
41811745SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_MIN_HEAP_SIZE	(64 * 1024 * sizeof (callout_heap_t))
41911745SMadhavan.Venkataraman@Sun.COM 
42011745SMadhavan.Venkataraman@Sun.COM /*
42111745SMadhavan.Venkataraman@Sun.COM  * CALLOUT_MEM_FRACTION defines the fraction of available physical memory that
42211745SMadhavan.Venkataraman@Sun.COM  * can be allocated towards the callout heap for the whole system.
42311745SMadhavan.Venkataraman@Sun.COM  */
42411745SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_MEM_FRACTION	4096
4258048SMadhavan.Venkataraman@Sun.COM 
4268048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_HEAP_PARENT(index)	(((index) - 1) >> 1)
4278048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_HEAP_RIGHT(index)	(((index) + 1) << 1)
4288048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_HEAP_LEFT(index)	((((index) + 1) << 1) - 1)
4298048SMadhavan.Venkataraman@Sun.COM 
4308048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_TCP_RESOLUTION		10000000ULL
4318048SMadhavan.Venkataraman@Sun.COM 
4328048SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_ALIGN	64	/* cache line size */
4338048SMadhavan.Venkataraman@Sun.COM 
4348566SMadhavan.Venkataraman@Sun.COM #ifdef _LP64
4358566SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_MAX_TICKS	NSEC_TO_TICK(CY_INFINITY);
4368566SMadhavan.Venkataraman@Sun.COM #else
4378566SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_MAX_TICKS	LONG_MAX
4388566SMadhavan.Venkataraman@Sun.COM #endif
4398566SMadhavan.Venkataraman@Sun.COM 
4409334SMadhavan.Venkataraman@Sun.COM #define	CALLOUT_TOLERANCE	200000		/* nanoseconds */
4419334SMadhavan.Venkataraman@Sun.COM 
4428048SMadhavan.Venkataraman@Sun.COM extern void		callout_init(void);
4438048SMadhavan.Venkataraman@Sun.COM extern void		membar_sync(void);
4448048SMadhavan.Venkataraman@Sun.COM extern void		callout_cpu_online(cpu_t *);
4458566SMadhavan.Venkataraman@Sun.COM extern void		callout_cpu_offline(cpu_t *);
4468048SMadhavan.Venkataraman@Sun.COM extern void		callout_hrestime(void);
4478566SMadhavan.Venkataraman@Sun.COM 
4480Sstevel@tonic-gate #endif
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate #ifdef	__cplusplus
4510Sstevel@tonic-gate }
4520Sstevel@tonic-gate #endif
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate #endif	/* _SYS_CALLO_H */
455