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 33 extern "C" { 34 #endif 35 36 #ifdef _KERNEL 37 38 /* 39 * Used by the new timeout functions 40 */ 41 typedef struct __timeout *timeout_t; 42 43 /* 44 * Forward declarations. 45 */ 46 struct cyc_timer; 47 struct 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 */ 54 typedef 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 */ 65 typedef 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 */ 91 typedef 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 */ 135 void timer_init(void); 136 void cyclic_timer(void); 137 void timer_softintr(int); 138 timeout_t i_timeout(void (*)(void *), void *, hrtime_t, int); 139 void i_untimeout(timeout_t); 140 141 #endif /* _KERNEL */ 142 143 #ifdef __cplusplus 144 } 145 #endif 146 147 #endif /* _SYS_DDI_TIMER_H */