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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#ifndef	_SYS_DDI_TIMER_H
28#define	_SYS_DDI_TIMER_H
29
30#include <sys/list.h>
31
32#ifdef	__cplusplus
33extern "C" {
34#endif
35
36#ifdef _KERNEL
37
38/*
39 * Used by the new timeout functions
40 */
41typedef struct __timeout *timeout_t;
42
43/*
44 * Forward declarations.
45 */
46struct cyc_timer;
47struct tm_req;
48
49/*
50 * Timing wheel cog.
51 * Each cog has a timeout request queue which is guarded by the lock
52 * here.
53 */
54typedef struct timer_tw {
55	list_t req;			/* timeout request queue */
56	kmutex_t lock;			/* lock for this queue */
57} timer_tw_t;
58
59/*
60 * Timer based on the cyclic subsystem.
61 * For each resolution, this timer structure should be allocated.
62 * Note. currently only one timer is used for periodic timeout requests,
63 * which is based on the system clock resolution.
64 */
65typedef struct cyc_timer {
66	hrtime_t res;			/* this cyclic resolution */
67	hrtime_t tick;			/* tick of this cyclic */
68	hrtime_t tick_time;		/* current time on this timer */
69/*
70 * The hash size might need to be tuned if the lock contention is
71 * observed. So far the current size (1024) is sufficient though.
72 */
73#define	TM_HASH_SZ	(1024)		/* must be power of 2 */
74#define	TM_HASH(x)	((x) & (TM_HASH_SZ -1))
75	timer_tw_t idhash[TM_HASH_SZ];	/* ID hash */
76	timer_tw_t exhash[TM_HASH_SZ];  /* expiration time hash */
77} cyc_timer_t;
78
79/*
80 * This value determines how many requests within 10ms can be allocated to
81 * different slots. This is an exponential number powered by 2.
82 * This value should be tuned with the hash size.
83 * Note. This value is fixed now, but can be adjusted by checking the number
84 * of CPUs when the timer structure is allocated.
85 */
86#define	TICK_FACTOR	(3)
87
88/*
89 * Timer request.
90 */
91typedef struct tm_req {
92	struct list_node id_req;	/* request on ID hash */
93	struct list_node ex_req;	/* request on expire hash */
94	struct list_node disp_req;	/* request on dispatch queue */
95	hrtime_t interval;	/* interval this request needs */
96	hrtime_t exp_time;	/* time when the request executes */
97	void (*handler)(void *);	/* timeout handler */
98	void *arg;		/* timeout argument */
99	kthread_t *h_thread;	/* handler thread */
100	kmutex_t lock;		/* lock for setting counter and flag */
101	kcondvar_t cv;		/* condition variable against the lock */
102	timeout_t id;		/* this request id */
103	int level;		/* interrupt level */
104	volatile uint_t flags;	/* flags passed to ddi_timeout() */
105	/*
106	 * State flags
107	 * These are used internally.
108	 */
109#define	TM_INVOKING	0x00000001	/* cyclic is invoked now */
110#define	TM_EXECUTING	0x00000002	/* timeout is executed now */
111#define	TM_CANCEL	0x00000004	/* request is canceled */
112#define	TM_TRANSFER	0x00000008	/* request is transfered */
113#define	TM_UTMCOMP	0x00000040	/* untimeout is complete */
114	uint_t cnt;		/* invoke counter */
115} tm_req_t;
116
117/*
118 * Software interrupt intr_state:
119 *
120 *  31              16 15               0
121 * +------------------+------------------+
122 * |  interrupt start |  interrupt set   |
123 * +------------------+------------------+
124 *
125 * Note. This structure can accomodate interrupts up to the level 15,
126 * but supported interrupts are up to the level 10 in practice because
127 * of the ddi timer restriction.
128 */
129#define	TM_INTR_SET(l)		(1 << (l))
130#define	TM_INTR_START(l)	(1 << ((l) + 16))
131
132/*
133 * internal functions for the ddi timeout
134 */
135void timer_init(void);
136void cyclic_timer(void);
137void timer_softintr(int);
138timeout_t i_timeout(void (*)(void *), void *, hrtime_t, int);
139void i_untimeout(timeout_t);
140
141#endif	/* _KERNEL */
142
143#ifdef	__cplusplus
144}
145#endif
146
147#endif	/* _SYS_DDI_TIMER_H */
148