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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #ifndef _SYS_LOCKSTAT_H 27 #define _SYS_LOCKSTAT_H 28 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 31 #include <sys/dtrace.h> 32 33 #ifdef __cplusplus 34 extern "C" { 35 #endif 36 37 #define LS_MUTEX_ENTER_ACQUIRE 0 38 #define LS_MUTEX_ENTER_BLOCK 1 39 #define LS_MUTEX_ENTER_SPIN 2 40 #define LS_MUTEX_EXIT_RELEASE 3 41 #define LS_MUTEX_DESTROY_RELEASE 4 42 #define LS_MUTEX_TRYENTER_ACQUIRE 5 43 #define LS_LOCK_SET_ACQUIRE 6 44 #define LS_LOCK_SET_SPIN 7 45 #define LS_LOCK_SET_SPL_ACQUIRE 8 46 #define LS_LOCK_SET_SPL_SPIN 9 47 #define LS_LOCK_TRY_ACQUIRE 10 48 #define LS_LOCK_CLEAR_RELEASE 11 49 #define LS_LOCK_CLEAR_SPLX_RELEASE 12 50 #define LS_CLOCK_UNLOCK_RELEASE 13 51 #define LS_RW_ENTER_ACQUIRE 14 52 #define LS_RW_ENTER_BLOCK 15 53 #define LS_RW_EXIT_RELEASE 16 54 #define LS_RW_TRYENTER_ACQUIRE 17 55 #define LS_RW_TRYUPGRADE_UPGRADE 18 56 #define LS_RW_DOWNGRADE_DOWNGRADE 19 57 #define LS_THREAD_LOCK_ACQUIRE 20 58 #define LS_THREAD_LOCK_SPIN 21 59 #define LS_THREAD_LOCK_HIGH_ACQUIRE 22 60 #define LS_THREAD_LOCK_HIGH_SPIN 23 61 #define LS_TURNSTILE_INTERLOCK_SPIN 24 62 #define LS_NPROBES 25 63 64 #define LS_MUTEX_ENTER "mutex_enter" 65 #define LS_MUTEX_EXIT "mutex_exit" 66 #define LS_MUTEX_DESTROY "mutex_destroy" 67 #define LS_MUTEX_TRYENTER "mutex_tryenter" 68 #define LS_LOCK_SET "lock_set" 69 #define LS_LOCK_SET_SPL "lock_set_spl" 70 #define LS_LOCK_TRY "lock_try" 71 #define LS_LOCK_CLEAR "lock_clear" 72 #define LS_LOCK_CLEAR_SPLX "lock_clear_splx" 73 #define LS_CLOCK_UNLOCK "CLOCK_UNLOCK" 74 #define LS_RW_ENTER "rw_enter" 75 #define LS_RW_EXIT "rw_exit" 76 #define LS_RW_TRYENTER "rw_tryenter" 77 #define LS_RW_TRYUPGRADE "rw_tryupgrade" 78 #define LS_RW_DOWNGRADE "rw_downgrade" 79 #define LS_THREAD_LOCK "thread_lock" 80 #define LS_THREAD_LOCK_HIGH "thread_lock_high" 81 82 #define LS_ACQUIRE "acquire" 83 #define LS_RELEASE "release" 84 #define LS_SPIN "spin" 85 #define LS_BLOCK "block" 86 #define LS_UPGRADE "upgrade" 87 #define LS_DOWNGRADE "downgrade" 88 89 #define LS_TYPE_ADAPTIVE "adaptive" 90 #define LS_TYPE_SPIN "spin" 91 #define LS_TYPE_THREAD "thread" 92 #define LS_TYPE_RW "rw" 93 94 #define LSA_ACQUIRE (LS_TYPE_ADAPTIVE "-" LS_ACQUIRE) 95 #define LSA_RELEASE (LS_TYPE_ADAPTIVE "-" LS_RELEASE) 96 #define LSA_SPIN (LS_TYPE_ADAPTIVE "-" LS_SPIN) 97 #define LSA_BLOCK (LS_TYPE_ADAPTIVE "-" LS_BLOCK) 98 #define LSS_ACQUIRE (LS_TYPE_SPIN "-" LS_ACQUIRE) 99 #define LSS_RELEASE (LS_TYPE_SPIN "-" LS_RELEASE) 100 #define LSS_SPIN (LS_TYPE_SPIN "-" LS_SPIN) 101 #define LSR_ACQUIRE (LS_TYPE_RW "-" LS_ACQUIRE) 102 #define LSR_RELEASE (LS_TYPE_RW "-" LS_RELEASE) 103 #define LSR_BLOCK (LS_TYPE_RW "-" LS_BLOCK) 104 #define LSR_UPGRADE (LS_TYPE_RW "-" LS_UPGRADE) 105 #define LSR_DOWNGRADE (LS_TYPE_RW "-" LS_DOWNGRADE) 106 #define LST_SPIN (LS_TYPE_THREAD "-" LS_SPIN) 107 108 #ifndef _ASM 109 110 #include <sys/types.h> 111 #include <sys/inttypes.h> 112 #include <sys/systm.h> 113 #include <sys/atomic.h> 114 115 #ifdef _KERNEL 116 117 /* 118 * Platform-independent kernel support for the lockstat driver. 119 */ 120 extern dtrace_id_t lockstat_probemap[LS_NPROBES]; 121 extern void (*lockstat_probe)(dtrace_id_t, uintptr_t, uintptr_t, 122 uintptr_t, uintptr_t, uintptr_t); 123 124 extern int lockstat_active_threads(void); 125 extern int lockstat_depth(void); 126 extern void lockstat_hot_patch(void); 127 128 /* 129 * Macros to record lockstat probes. 130 */ 131 132 /* used for 32 bit systems to avoid overflow */ 133 #if defined(_ILP32) 134 #define CLAMP32(x) ((x) > UINT_MAX ? UINT_MAX : (x)) 135 #else 136 #define CLAMP32(x) (x) 137 #endif 138 139 #define LOCKSTAT_RECORD4(probe, lp, arg0, arg1, arg2, arg3) \ 140 if (lockstat_probemap[(probe)]) { \ 141 dtrace_id_t id; \ 142 curthread->t_lockstat++; \ 143 membar_enter(); \ 144 if ((id = lockstat_probemap[(probe)]) != 0) \ 145 (*lockstat_probe)(id, (uintptr_t)(lp), (arg0), \ 146 (arg1), (arg2), (arg3)); \ 147 curthread->t_lockstat--; \ 148 } 149 150 #define LOCKSTAT_RECORD(probe, lp, arg) \ 151 LOCKSTAT_RECORD4(probe, lp, arg, 0, 0, 0) 152 153 #define LOCKSTAT_RECORD0(probe, lp) \ 154 LOCKSTAT_RECORD4(probe, lp, 0, 0, 0, 0) 155 156 /* 157 * Return timestamp for start of busy-waiting (for spin probes) 158 */ 159 #define LOCKSTAT_START_TIME(probe) ( \ 160 lockstat_probemap[(probe)] ? gethrtime_waitfree() : 0 \ 161 ) 162 163 /* 164 * Record elapsed time since LOCKSTAT_START_TIME was called if the 165 * probe is enabled at start and end, else return 0. t_start must 166 * be the value returned by LOCKSTAT_START_TIME. 167 */ 168 #define LOCKSTAT_RECORD_TIME(probe, lp, t_start) \ 169 if (lockstat_probemap[(probe)]) { \ 170 dtrace_id_t id; \ 171 hrtime_t t_spin = (t_start); \ 172 curthread->t_lockstat++; \ 173 membar_enter(); \ 174 if ((id = lockstat_probemap[(probe)]) != 0) { \ 175 if (t_spin) { \ 176 t_spin = gethrtime_waitfree() - t_spin; \ 177 t_spin = CLAMP32(t_spin); \ 178 } \ 179 (*lockstat_probe)(id, (uintptr_t)(lp), t_spin, \ 180 0, 0, 0); \ 181 } \ 182 curthread->t_lockstat--; \ 183 } 184 185 186 #endif /* _KERNEL */ 187 188 #endif /* _ASM */ 189 190 #ifdef __cplusplus 191 } 192 #endif 193 194 #endif /* _SYS_LOCKSTAT_H */ 195