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 */