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