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 2007 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 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #include <sys/list.h> 33 34 #ifdef __cplusplus 35 extern "C" { 36 #endif 37 38 #ifdef _KERNEL 39 40 /* 41 * Used by the new timeout functions 42 */ 43 typedef struct __timeout *timeout_t; 44 45 /* 46 * Forward declarations. 47 */ 48 struct cyc_timer; 49 struct tm_req; 50 51 /* 52 * Timing wheel cog. 53 * Each cog has a timeout request queue which is guarded by the lock 54 * here. 55 */ 56 typedef struct timer_tw { 57 list_t req; /* timeout request queue */ 58 kmutex_t lock; /* lock for this queue */ 59 } timer_tw_t; 60 61 /* 62 * Timer based on the cyclic subsystem. 63 * For each resolution, this timer structure should be allocated. 64 * Note. currently only one timer is used for periodic timeout requests, 65 * which is based on the system clock resolution. 66 */ 67 typedef struct cyc_timer { 68 hrtime_t res; /* this cyclic resolution */ 69 hrtime_t tick; /* tick of this cyclic */ 70 hrtime_t tick_time; /* current time on this timer */ 71 /* 72 * The hash size might need to be tuned if the lock contention is 73 * observed. So far the current size (1024) is sufficient though. 74 */ 75 #define TM_HASH_SZ (1024) /* must be power of 2 */ 76 #define TM_HASH(x) ((x) & (TM_HASH_SZ -1)) 77 timer_tw_t idhash[TM_HASH_SZ]; /* ID hash */ 78 timer_tw_t exhash[TM_HASH_SZ]; /* expiration time hash */ 79 } cyc_timer_t; 80 81 /* 82 * This value determines how many requests within 10ms can be allocated to 83 * different slots. This is an exponential number powered by 2. 84 * This value should be tuned with the hash size. 85 * Note. This value is fixed now, but can be adjusted by checking the number 86 * of CPUs when the timer structure is allocated. 87 */ 88 #define TICK_FACTOR (3) 89 90 /* 91 * Timer request. 92 */ 93 typedef struct tm_req { 94 struct list_node id_req; /* request on ID hash */ 95 struct list_node ex_req; /* request on expire hash */ 96 struct list_node disp_req; /* request on dispatch queue */ 97 hrtime_t interval; /* interval this request needs */ 98 hrtime_t exp_time; /* time when the request executes */ 99 void (*handler)(void *); /* timeout handler */ 100 void *arg; /* timeout argument */ 101 kthread_t *h_thread; /* handler thread */ 102 kmutex_t lock; /* lock for setting counter and flag */ 103 kcondvar_t cv; /* condition variable against the lock */ 104 timeout_t id; /* this request id */ 105 int level; /* interrupt level */ 106 volatile uint_t flags; /* flags passed to ddi_timeout() */ 107 /* 108 * State flags 109 * These are used internally. 110 */ 111 #define TM_INVOKING 0x00000001 /* cyclic is invoked now */ 112 #define TM_EXECUTING 0x00000002 /* timeout is executed now */ 113 #define TM_CANCEL 0x00000004 /* request is canceled */ 114 #define TM_TRANSFER 0x00000008 /* request is transfered */ 115 #define TM_COMPLETE 0x00000010 /* request is complete */ 116 #define TM_COMPWAIT 0x00000020 /* wait request completion */ 117 #define TM_UTMCOMP 0x00000040 /* untimeout is complete */ 118 uint_t cnt; /* invoke counter */ 119 } tm_req_t; 120 121 /* 122 * Software interrupt intr_state: 123 * 124 * 31 16 15 0 125 * +------------------+------------------+ 126 * | interrupt start | interrupt set | 127 * +------------------+------------------+ 128 * 129 * Note. This structure can accomodate interrupts up to the level 15, 130 * but supported interrupts are up to the level 10 in practice because 131 * of the ddi timer restriction. 132 */ 133 #define TM_INTR_SET(l) (1 << (l)) 134 #define TM_INTR_START(l) (1 << ((l) + 16)) 135 136 /* 137 * internal functions for the ddi timeout 138 */ 139 void timer_init(void); 140 void cyclic_timer(void); 141 void timer_softintr(int); 142 timeout_t i_timeout(void (*)(void *), void *, hrtime_t, int); 143 void i_untimeout(timeout_t); 144 145 #endif /* _KERNEL */ 146 147 #ifdef __cplusplus 148 } 149 #endif 150 151 #endif /* _SYS_DDI_TIMER_H */ 152