1d3d50737SRafael Vanoni /* 2d3d50737SRafael Vanoni * CDDL HEADER START 3d3d50737SRafael Vanoni * 4d3d50737SRafael Vanoni * The contents of this file are subject to the terms of the 5d3d50737SRafael Vanoni * Common Development and Distribution License (the "License"). 6d3d50737SRafael Vanoni * You may not use this file except in compliance with the License. 7d3d50737SRafael Vanoni * 8d3d50737SRafael Vanoni * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9d3d50737SRafael Vanoni * or http://www.opensolaris.org/os/licensing. 10d3d50737SRafael Vanoni * See the License for the specific language governing permissions 11d3d50737SRafael Vanoni * and limitations under the License. 12d3d50737SRafael Vanoni * 13d3d50737SRafael Vanoni * When distributing Covered Code, include this CDDL HEADER in each 14d3d50737SRafael Vanoni * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15d3d50737SRafael Vanoni * If applicable, add the following below this CDDL HEADER, with the 16d3d50737SRafael Vanoni * fields enclosed by brackets "[]" replaced with your own identifying 17d3d50737SRafael Vanoni * information: Portions Copyright [yyyy] [name of copyright owner] 18d3d50737SRafael Vanoni * 19d3d50737SRafael Vanoni * CDDL HEADER END 20d3d50737SRafael Vanoni */ 21d3d50737SRafael Vanoni 22d3d50737SRafael Vanoni /* 23d3d50737SRafael Vanoni * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24d3d50737SRafael Vanoni * Use is subject to license terms. 25d3d50737SRafael Vanoni */ 26d3d50737SRafael Vanoni 27d3d50737SRafael Vanoni #ifndef _SYS_CLOCK_IMPL_H 28d3d50737SRafael Vanoni #define _SYS_CLOCK_IMPL_H 29d3d50737SRafael Vanoni 30d3d50737SRafael Vanoni #ifdef __cplusplus 31d3d50737SRafael Vanoni extern "C" { 32d3d50737SRafael Vanoni #endif 33d3d50737SRafael Vanoni 34d3d50737SRafael Vanoni #if (defined(_KERNEL) || defined(_KMEMUSER)) 35d3d50737SRafael Vanoni #include <sys/types.h> 36d3d50737SRafael Vanoni #include <sys/cpuvar.h> 37d3d50737SRafael Vanoni #include <sys/cyclic.h> 38d3d50737SRafael Vanoni #include <sys/time.h> 39d3d50737SRafael Vanoni 40d3d50737SRafael Vanoni /* 41d3d50737SRafael Vanoni * Default clock rate in Hz. 42d3d50737SRafael Vanoni */ 43579a6895SRafael Vanoni #define HZ_DEFAULT (100) 44d3d50737SRafael Vanoni 45d3d50737SRafael Vanoni /* 46d3d50737SRafael Vanoni * Thresholds over which we switch between event and cyclic driven lbolt. The 47d3d50737SRafael Vanoni * current default values were derived experimentally and will keep the 48d3d50737SRafael Vanoni * system on event driven mode when idle and respond to activity around the 49d3d50737SRafael Vanoni * lbolt DDI functions by switching to cyclic mode. 50d3d50737SRafael Vanoni */ 51d3d50737SRafael Vanoni #define LBOLT_THRESH_CALLS (75) 52d3d50737SRafael Vanoni #define LBOLT_THRESH_INTERVAL (1) 53d3d50737SRafael Vanoni 54d3d50737SRafael Vanoni /* 55d3d50737SRafael Vanoni * Both lbolt_cpu_t and lbolt_info_t are cache line sized and aligned, 56d3d50737SRafael Vanoni * please take that in consideration if modifying these. 57d3d50737SRafael Vanoni */ 58d3d50737SRafael Vanoni typedef struct lbolt_cpu { 59d3d50737SRafael Vanoni int64_t lbc_counter; /* number of calls to the DDI lbolt routines */ 60d3d50737SRafael Vanoni int64_t lbc_cnt_start; /* beggining of the cnt interval (in ticks) */ 61d3d50737SRafael Vanoni char lbc_pad[CPU_CACHE_COHERENCE_SIZE - (2 * sizeof (int64_t))]; 62d3d50737SRafael Vanoni } lbolt_cpu_t; 63d3d50737SRafael Vanoni 64d3d50737SRafael Vanoni typedef struct lbolt_info { 65579a6895SRafael Vanoni union { 66579a6895SRafael Vanoni cyclic_id_t lbi_cyclic_id; /* lbolt's cyclic id */ 67579a6895SRafael Vanoni int64_t lbi_id_pad; /* 64bit padding */ 68579a6895SRafael Vanoni } id; 69d3d50737SRafael Vanoni int64_t lbi_internal; /* lbolt source when on cyclic mode */ 70d3d50737SRafael Vanoni int64_t lbi_debug_time; /* time spent in the debugger */ 71d3d50737SRafael Vanoni int64_t lbi_debug_ts; /* last time we dropped into kmdb */ 72d3d50737SRafael Vanoni int64_t lbi_thresh_calls; /* max calls per interval */ 73d3d50737SRafael Vanoni int64_t lbi_thresh_interval; /* interval window for the # of calls */ 74d3d50737SRafael Vanoni uint32_t lbi_token; /* synchronize cyclic mode switch */ 75d3d50737SRafael Vanoni boolean_t lbi_cyc_deactivate; /* lbolt_cyclic self deactivation */ 76d3d50737SRafael Vanoni int64_t lbi_cyc_deac_start; /* deactivation interval */ 77d3d50737SRafael Vanoni } lbolt_info_t; 78d3d50737SRafael Vanoni 79*83e866b9SRafael Vanoni extern int64_t lbolt_bootstrap(void); 80d3d50737SRafael Vanoni extern int64_t lbolt_event_driven(void); 81d3d50737SRafael Vanoni extern int64_t lbolt_cyclic_driven(void); 82d3d50737SRafael Vanoni extern int64_t (*lbolt_hybrid)(void); 83d3d50737SRafael Vanoni extern uint_t lbolt_ev_to_cyclic(caddr_t, caddr_t); 84d3d50737SRafael Vanoni 85d3d50737SRafael Vanoni extern void lbolt_softint_add(void); 86d3d50737SRafael Vanoni extern void lbolt_softint_post(void); 87d3d50737SRafael Vanoni 88d3d50737SRafael Vanoni extern void lbolt_debug_entry(void); 89d3d50737SRafael Vanoni extern void lbolt_debug_return(void); 90d3d50737SRafael Vanoni 91d3d50737SRafael Vanoni extern lbolt_info_t *lb_info; 92d3d50737SRafael Vanoni 93d3d50737SRafael Vanoni /* 941b7f7204SRafael Vanoni * LBOLT_WAITFREE{,64} provide a non-waiting version of lbolt. 95d3d50737SRafael Vanoni */ 961b7f7204SRafael Vanoni #define LBOLT_WAITFREE64 \ 97*83e866b9SRafael Vanoni (lbolt_hybrid == lbolt_bootstrap ? 0 : \ 98d3d50737SRafael Vanoni (lbolt_hybrid == lbolt_event_driven ? \ 99d3d50737SRafael Vanoni ((gethrtime_waitfree()/nsec_per_tick) - \ 100d3d50737SRafael Vanoni lb_info->lbi_debug_time) : \ 101*83e866b9SRafael Vanoni (lb_info->lbi_internal - lb_info->lbi_debug_time))) 102d3d50737SRafael Vanoni 1031b7f7204SRafael Vanoni #define LBOLT_WAITFREE (clock_t)LBOLT_WAITFREE64 1041b7f7204SRafael Vanoni 105d3d50737SRafael Vanoni /* 1061b7f7204SRafael Vanoni * LBOLT_FASTPATH{,64} should *only* be used where the cost of calling the 1071b7f7204SRafael Vanoni * DDI lbolt routines affects performance. This is currently only used by 1081b7f7204SRafael Vanoni * the TCP/IP code and will be removed once it's no longer required. 109d3d50737SRafael Vanoni */ 1101b7f7204SRafael Vanoni #define LBOLT_FASTPATH64 \ 111*83e866b9SRafael Vanoni (lbolt_hybrid == lbolt_cyclic_driven ? \ 112*83e866b9SRafael Vanoni (lb_info->lbi_internal - lb_info->lbi_debug_time) : \ 113*83e866b9SRafael Vanoni ddi_get_lbolt64()) 1141b7f7204SRafael Vanoni 1151b7f7204SRafael Vanoni #define LBOLT_FASTPATH (clock_t)LBOLT_FASTPATH64 116d3d50737SRafael Vanoni 117d3d50737SRafael Vanoni /* 1181b7f7204SRafael Vanoni * LBOLT_NO_ACCOUNT{,64} is used by lbolt consumers who fire at a periodic 1191b7f7204SRafael Vanoni * rate, such as clock(), for which the lbolt usage statistics are not updated. 1201b7f7204SRafael Vanoni * This is especially important for consumers whose rate may be modified by 121d3d50737SRafael Vanoni * the user, resulting in an unaccounted for increase in activity around the 122d3d50737SRafael Vanoni * lbolt routines that could cause a mode switch. 123d3d50737SRafael Vanoni */ 1241b7f7204SRafael Vanoni #define LBOLT_NO_ACCOUNT64 \ 125*83e866b9SRafael Vanoni (lbolt_hybrid == lbolt_bootstrap ? 0 : \ 126d3d50737SRafael Vanoni (lbolt_hybrid == lbolt_event_driven ? \ 127d3d50737SRafael Vanoni ((gethrtime()/nsec_per_tick) - lb_info->lbi_debug_time) : \ 128*83e866b9SRafael Vanoni (lb_info->lbi_internal - lb_info->lbi_debug_time))) 129d3d50737SRafael Vanoni 1301b7f7204SRafael Vanoni #define LBOLT_NO_ACCOUNT (clock_t)LBOLT_NO_ACCOUNT64 1311b7f7204SRafael Vanoni 132d3d50737SRafael Vanoni #endif /* _KERNEL || _KMEMUSER */ 133d3d50737SRafael Vanoni 134d3d50737SRafael Vanoni #ifdef __cplusplus 135d3d50737SRafael Vanoni } 136d3d50737SRafael Vanoni #endif 137d3d50737SRafael Vanoni 138d3d50737SRafael Vanoni #endif /* _SYS_CLOCK_IMPL_H */ 139