xref: /onnv-gate/usr/src/uts/common/sys/ddi_timer.h (revision 9314:4be129136bf2)
15107Seota /*
25107Seota  * CDDL HEADER START
35107Seota  *
45107Seota  * The contents of this file are subject to the terms of the
55107Seota  * Common Development and Distribution License (the "License").
65107Seota  * You may not use this file except in compliance with the License.
75107Seota  *
85107Seota  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95107Seota  * or http://www.opensolaris.org/os/licensing.
105107Seota  * See the License for the specific language governing permissions
115107Seota  * and limitations under the License.
125107Seota  *
135107Seota  * When distributing Covered Code, include this CDDL HEADER in each
145107Seota  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155107Seota  * If applicable, add the following below this CDDL HEADER, with the
165107Seota  * fields enclosed by brackets "[]" replaced with your own identifying
175107Seota  * information: Portions Copyright [yyyy] [name of copyright owner]
185107Seota  *
195107Seota  * CDDL HEADER END
205107Seota  */
215107Seota 
225107Seota /*
23*9314SEiji.Ota@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
245107Seota  * Use is subject to license terms.
255107Seota  */
265107Seota 
275107Seota #ifndef	_SYS_DDI_TIMER_H
285107Seota #define	_SYS_DDI_TIMER_H
295107Seota 
305107Seota #include <sys/list.h>
315107Seota 
325107Seota #ifdef	__cplusplus
335107Seota extern "C" {
345107Seota #endif
355107Seota 
365107Seota #ifdef _KERNEL
375107Seota 
385107Seota /*
395107Seota  * Used by the new timeout functions
405107Seota  */
415107Seota typedef struct __timeout *timeout_t;
425107Seota 
435107Seota /*
445107Seota  * Forward declarations.
455107Seota  */
465107Seota struct cyc_timer;
475107Seota struct tm_req;
485107Seota 
495107Seota /*
505107Seota  * Timing wheel cog.
515107Seota  * Each cog has a timeout request queue which is guarded by the lock
525107Seota  * here.
535107Seota  */
545107Seota typedef struct timer_tw {
555107Seota 	list_t req;			/* timeout request queue */
565107Seota 	kmutex_t lock;			/* lock for this queue */
575107Seota } timer_tw_t;
585107Seota 
595107Seota /*
605107Seota  * Timer based on the cyclic subsystem.
615107Seota  * For each resolution, this timer structure should be allocated.
625107Seota  * Note. currently only one timer is used for periodic timeout requests,
635107Seota  * which is based on the system clock resolution.
645107Seota  */
655107Seota typedef struct cyc_timer {
665107Seota 	hrtime_t res;			/* this cyclic resolution */
675107Seota 	hrtime_t tick;			/* tick of this cyclic */
685107Seota 	hrtime_t tick_time;		/* current time on this timer */
695107Seota /*
705107Seota  * The hash size might need to be tuned if the lock contention is
715107Seota  * observed. So far the current size (1024) is sufficient though.
725107Seota  */
735107Seota #define	TM_HASH_SZ	(1024)		/* must be power of 2 */
745107Seota #define	TM_HASH(x)	((x) & (TM_HASH_SZ -1))
755107Seota 	timer_tw_t idhash[TM_HASH_SZ];	/* ID hash */
765107Seota 	timer_tw_t exhash[TM_HASH_SZ];  /* expiration time hash */
775107Seota } cyc_timer_t;
785107Seota 
795107Seota /*
805107Seota  * This value determines how many requests within 10ms can be allocated to
815107Seota  * different slots. This is an exponential number powered by 2.
825107Seota  * This value should be tuned with the hash size.
835107Seota  * Note. This value is fixed now, but can be adjusted by checking the number
845107Seota  * of CPUs when the timer structure is allocated.
855107Seota  */
865107Seota #define	TICK_FACTOR	(3)
875107Seota 
885107Seota /*
895107Seota  * Timer request.
905107Seota  */
915107Seota typedef struct tm_req {
925107Seota 	struct list_node id_req;	/* request on ID hash */
935107Seota 	struct list_node ex_req;	/* request on expire hash */
945107Seota 	struct list_node disp_req;	/* request on dispatch queue */
955107Seota 	hrtime_t interval;	/* interval this request needs */
965107Seota 	hrtime_t exp_time;	/* time when the request executes */
975107Seota 	void (*handler)(void *);	/* timeout handler */
985107Seota 	void *arg;		/* timeout argument */
995107Seota 	kthread_t *h_thread;	/* handler thread */
1005107Seota 	kmutex_t lock;		/* lock for setting counter and flag */
1015107Seota 	kcondvar_t cv;		/* condition variable against the lock */
1025107Seota 	timeout_t id;		/* this request id */
1035107Seota 	int level;		/* interrupt level */
1045107Seota 	volatile uint_t flags;	/* flags passed to ddi_timeout() */
1055107Seota 	/*
1065107Seota 	 * State flags
1075107Seota 	 * These are used internally.
1085107Seota 	 */
1095107Seota #define	TM_INVOKING	0x00000001	/* cyclic is invoked now */
1105107Seota #define	TM_EXECUTING	0x00000002	/* timeout is executed now */
1115107Seota #define	TM_CANCEL	0x00000004	/* request is canceled */
1125107Seota #define	TM_TRANSFER	0x00000008	/* request is transfered */
1135107Seota #define	TM_UTMCOMP	0x00000040	/* untimeout is complete */
1145107Seota 	uint_t cnt;		/* invoke counter */
1155107Seota } tm_req_t;
1165107Seota 
1175107Seota /*
1185107Seota  * Software interrupt intr_state:
1195107Seota  *
1205107Seota  *  31              16 15               0
1215107Seota  * +------------------+------------------+
1225107Seota  * |  interrupt start |  interrupt set   |
1235107Seota  * +------------------+------------------+
1245107Seota  *
1255107Seota  * Note. This structure can accomodate interrupts up to the level 15,
1265107Seota  * but supported interrupts are up to the level 10 in practice because
1275107Seota  * of the ddi timer restriction.
1285107Seota  */
1295107Seota #define	TM_INTR_SET(l)		(1 << (l))
1305107Seota #define	TM_INTR_START(l)	(1 << ((l) + 16))
1315107Seota 
1325107Seota /*
1335107Seota  * internal functions for the ddi timeout
1345107Seota  */
1355107Seota void timer_init(void);
1365107Seota void cyclic_timer(void);
1375107Seota void timer_softintr(int);
1385107Seota timeout_t i_timeout(void (*)(void *), void *, hrtime_t, int);
1395107Seota void i_untimeout(timeout_t);
1405107Seota 
1415107Seota #endif	/* _KERNEL */
1425107Seota 
1435107Seota #ifdef	__cplusplus
1445107Seota }
1455107Seota #endif
1465107Seota 
1475107Seota #endif	/* _SYS_DDI_TIMER_H */
148