1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 1998-2003 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/types.h> 30*0Sstevel@tonic-gate #include <sys/kmem.h> 31*0Sstevel@tonic-gate #include <sys/mutex.h> 32*0Sstevel@tonic-gate #include <sys/cpuvar.h> 33*0Sstevel@tonic-gate #include <sys/cmn_err.h> 34*0Sstevel@tonic-gate #include <sys/systm.h> 35*0Sstevel@tonic-gate #include <sys/ddi.h> 36*0Sstevel@tonic-gate #include <sys/sunddi.h> 37*0Sstevel@tonic-gate #include <sys/debug.h> 38*0Sstevel@tonic-gate #include <sys/param.h> 39*0Sstevel@tonic-gate #include <sys/atomic.h> 40*0Sstevel@tonic-gate #include <sys/ftrace.h> 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate /* 43*0Sstevel@tonic-gate * Tunable parameters: 44*0Sstevel@tonic-gate * 45*0Sstevel@tonic-gate * ftrace_atboot - whether to start fast tracing at boot. 46*0Sstevel@tonic-gate * ftrace_nent - size of the per-CPU event ring buffer. 47*0Sstevel@tonic-gate */ 48*0Sstevel@tonic-gate int ftrace_atboot = 0; 49*0Sstevel@tonic-gate int ftrace_nent = FTRACE_NENT; 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate /* 52*0Sstevel@tonic-gate * The current overall state of the ftrace subsystem. 53*0Sstevel@tonic-gate * If FTRACE_READY is set, then tracing can be enabled. 54*0Sstevel@tonic-gate * If FTRACE_ENABLED is set, tracing is enabled on the set of CPUs 55*0Sstevel@tonic-gate * which are currently FTRACE_READY. 56*0Sstevel@tonic-gate */ 57*0Sstevel@tonic-gate static int ftrace_state = 0; 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate /* 60*0Sstevel@tonic-gate * Protects assignments to: 61*0Sstevel@tonic-gate * ftrace_state 62*0Sstevel@tonic-gate * cpu[N]->cpu_ftrace.ftd_state 63*0Sstevel@tonic-gate * cpu[N]->cpu_ftrace.ftd_cur 64*0Sstevel@tonic-gate * cpu[N]->cpu_ftrace.ftd_first 65*0Sstevel@tonic-gate * cpu[N]->cpu_ftrace.ftd_last 66*0Sstevel@tonic-gate * Does _not_ protect readers of cpu[N]->cpu_ftrace.ftd_state. 67*0Sstevel@tonic-gate * Does not protect reading the FTRACE_READY bit in ftrace_state, 68*0Sstevel@tonic-gate * since non-READY to READY is a stable transition. This is used 69*0Sstevel@tonic-gate * to ensure ftrace_init() has been called. 70*0Sstevel@tonic-gate */ 71*0Sstevel@tonic-gate static kmutex_t ftrace_lock; 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate /* 74*0Sstevel@tonic-gate * Check whether a CPU is installed. 75*0Sstevel@tonic-gate */ 76*0Sstevel@tonic-gate #define IS_CPU(i) (cpu[i] != NULL) 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate static void 79*0Sstevel@tonic-gate ftrace_cpu_init(int cpuid) 80*0Sstevel@tonic-gate { 81*0Sstevel@tonic-gate ftrace_data_t *ftd; 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate /* 84*0Sstevel@tonic-gate * This can be called with "cpu[cpuid]->cpu_flags & CPU_EXISTS" 85*0Sstevel@tonic-gate * being false - e.g. when a CPU is DR'ed in. 86*0Sstevel@tonic-gate */ 87*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ftrace_lock)); 88*0Sstevel@tonic-gate ASSERT(IS_CPU(cpuid)); 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate ftd = &cpu[cpuid]->cpu_ftrace; 91*0Sstevel@tonic-gate if (ftd->ftd_state & FTRACE_READY) 92*0Sstevel@tonic-gate return; 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate /* 95*0Sstevel@tonic-gate * We don't allocate the buffers until the first time 96*0Sstevel@tonic-gate * ftrace_cpu_start() is called, so that they're not 97*0Sstevel@tonic-gate * allocated if ftrace is never enabled. 98*0Sstevel@tonic-gate */ 99*0Sstevel@tonic-gate ftd->ftd_state |= FTRACE_READY; 100*0Sstevel@tonic-gate ASSERT(!(ftd->ftd_state & FTRACE_ENABLED)); 101*0Sstevel@tonic-gate } 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate /* 104*0Sstevel@tonic-gate * Only called from cpu_unconfigure() (and cpu_configure() on error). 105*0Sstevel@tonic-gate * At this point, cpu[cpuid] is about to be freed and NULLed out, 106*0Sstevel@tonic-gate * so we'd better clean up after ourselves. 107*0Sstevel@tonic-gate */ 108*0Sstevel@tonic-gate static void 109*0Sstevel@tonic-gate ftrace_cpu_fini(int cpuid) 110*0Sstevel@tonic-gate { 111*0Sstevel@tonic-gate ftrace_data_t *ftd; 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ftrace_lock)); 114*0Sstevel@tonic-gate ASSERT(IS_CPU(cpuid)); 115*0Sstevel@tonic-gate ASSERT((cpu[cpuid]->cpu_flags & CPU_POWEROFF) != 0); 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate ftd = &cpu[cpuid]->cpu_ftrace; 118*0Sstevel@tonic-gate if (!(ftd->ftd_state & FTRACE_READY)) 119*0Sstevel@tonic-gate return; 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate /* 122*0Sstevel@tonic-gate * Do not free mutex and the the trace buffer once they are 123*0Sstevel@tonic-gate * allocated. A thread, preempted from the now powered-off CPU 124*0Sstevel@tonic-gate * may be holding the mutex and in the middle of adding a trace 125*0Sstevel@tonic-gate * record. 126*0Sstevel@tonic-gate */ 127*0Sstevel@tonic-gate } 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gate static void 130*0Sstevel@tonic-gate ftrace_cpu_start(int cpuid) 131*0Sstevel@tonic-gate { 132*0Sstevel@tonic-gate ftrace_data_t *ftd; 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ftrace_lock)); 135*0Sstevel@tonic-gate ASSERT(IS_CPU(cpuid)); 136*0Sstevel@tonic-gate ASSERT(ftrace_state & FTRACE_ENABLED); 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate ftd = &cpu[cpuid]->cpu_ftrace; 139*0Sstevel@tonic-gate if (ftd->ftd_state & FTRACE_READY) { 140*0Sstevel@tonic-gate if (ftd->ftd_first == NULL) { 141*0Sstevel@tonic-gate ftrace_record_t *ptrs; 142*0Sstevel@tonic-gate 143*0Sstevel@tonic-gate mutex_init(&ftd->ftd_mutex, NULL, MUTEX_DEFAULT, NULL); 144*0Sstevel@tonic-gate mutex_exit(&ftrace_lock); 145*0Sstevel@tonic-gate ptrs = kmem_zalloc(ftrace_nent * 146*0Sstevel@tonic-gate sizeof (ftrace_record_t), KM_SLEEP); 147*0Sstevel@tonic-gate mutex_enter(&ftrace_lock); 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate ftd->ftd_first = ptrs; 150*0Sstevel@tonic-gate ftd->ftd_last = ptrs + (ftrace_nent - 1); 151*0Sstevel@tonic-gate ftd->ftd_cur = ptrs; 152*0Sstevel@tonic-gate membar_producer(); 153*0Sstevel@tonic-gate } 154*0Sstevel@tonic-gate ftd->ftd_state |= FTRACE_ENABLED; 155*0Sstevel@tonic-gate } 156*0Sstevel@tonic-gate } 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gate static void 159*0Sstevel@tonic-gate ftrace_cpu_stop(int cpuid) 160*0Sstevel@tonic-gate { 161*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ftrace_lock)); 162*0Sstevel@tonic-gate ASSERT(IS_CPU(cpuid)); 163*0Sstevel@tonic-gate cpu[cpuid]->cpu_ftrace.ftd_state &= ~(FTRACE_ENABLED); 164*0Sstevel@tonic-gate } 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate /* 167*0Sstevel@tonic-gate * Hook for DR. 168*0Sstevel@tonic-gate */ 169*0Sstevel@tonic-gate /*ARGSUSED*/ 170*0Sstevel@tonic-gate int 171*0Sstevel@tonic-gate ftrace_cpu_setup(cpu_setup_t what, int id, void *arg) 172*0Sstevel@tonic-gate { 173*0Sstevel@tonic-gate if (!(ftrace_state & FTRACE_READY)) 174*0Sstevel@tonic-gate return (0); 175*0Sstevel@tonic-gate 176*0Sstevel@tonic-gate switch (what) { 177*0Sstevel@tonic-gate case CPU_CONFIG: 178*0Sstevel@tonic-gate mutex_enter(&ftrace_lock); 179*0Sstevel@tonic-gate ftrace_cpu_init(id); 180*0Sstevel@tonic-gate if (ftrace_state & FTRACE_ENABLED) 181*0Sstevel@tonic-gate ftrace_cpu_start(id); 182*0Sstevel@tonic-gate mutex_exit(&ftrace_lock); 183*0Sstevel@tonic-gate break; 184*0Sstevel@tonic-gate 185*0Sstevel@tonic-gate case CPU_UNCONFIG: 186*0Sstevel@tonic-gate mutex_enter(&ftrace_lock); 187*0Sstevel@tonic-gate ftrace_cpu_fini(id); 188*0Sstevel@tonic-gate mutex_exit(&ftrace_lock); 189*0Sstevel@tonic-gate break; 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gate default: 192*0Sstevel@tonic-gate break; 193*0Sstevel@tonic-gate } 194*0Sstevel@tonic-gate return (0); 195*0Sstevel@tonic-gate } 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate void 198*0Sstevel@tonic-gate ftrace_init(void) 199*0Sstevel@tonic-gate { 200*0Sstevel@tonic-gate int i; 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate ASSERT(!(ftrace_state & FTRACE_READY)); 203*0Sstevel@tonic-gate mutex_init(&ftrace_lock, NULL, MUTEX_DEFAULT, NULL); 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate mutex_enter(&ftrace_lock); 206*0Sstevel@tonic-gate for (i = 0; i < NCPU; i++) { 207*0Sstevel@tonic-gate if (IS_CPU(i)) { 208*0Sstevel@tonic-gate /* should have been kmem_zalloc()'ed */ 209*0Sstevel@tonic-gate ASSERT(cpu[i]->cpu_ftrace.ftd_state == 0); 210*0Sstevel@tonic-gate ASSERT(cpu[i]->cpu_ftrace.ftd_first == NULL); 211*0Sstevel@tonic-gate ASSERT(cpu[i]->cpu_ftrace.ftd_last == NULL); 212*0Sstevel@tonic-gate ASSERT(cpu[i]->cpu_ftrace.ftd_cur == NULL); 213*0Sstevel@tonic-gate } 214*0Sstevel@tonic-gate } 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate if (ftrace_nent < 1) { 217*0Sstevel@tonic-gate mutex_exit(&ftrace_lock); 218*0Sstevel@tonic-gate return; 219*0Sstevel@tonic-gate } 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate for (i = 0; i < NCPU; i++) 222*0Sstevel@tonic-gate if (IS_CPU(i)) 223*0Sstevel@tonic-gate ftrace_cpu_init(i); 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate ftrace_state |= FTRACE_READY; 226*0Sstevel@tonic-gate mutex_enter(&cpu_lock); 227*0Sstevel@tonic-gate register_cpu_setup_func(ftrace_cpu_setup, NULL); 228*0Sstevel@tonic-gate mutex_exit(&cpu_lock); 229*0Sstevel@tonic-gate mutex_exit(&ftrace_lock); 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate if (ftrace_atboot) 232*0Sstevel@tonic-gate (void) ftrace_start(); 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate int 236*0Sstevel@tonic-gate ftrace_start(void) 237*0Sstevel@tonic-gate { 238*0Sstevel@tonic-gate int i, was_enabled = 0; 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate if (ftrace_state & FTRACE_READY) { 241*0Sstevel@tonic-gate mutex_enter(&ftrace_lock); 242*0Sstevel@tonic-gate was_enabled = ((ftrace_state & FTRACE_ENABLED) != 0); 243*0Sstevel@tonic-gate ftrace_state |= FTRACE_ENABLED; 244*0Sstevel@tonic-gate for (i = 0; i < NCPU; i++) 245*0Sstevel@tonic-gate if (IS_CPU(i)) 246*0Sstevel@tonic-gate ftrace_cpu_start(i); 247*0Sstevel@tonic-gate mutex_exit(&ftrace_lock); 248*0Sstevel@tonic-gate } 249*0Sstevel@tonic-gate 250*0Sstevel@tonic-gate return (was_enabled); 251*0Sstevel@tonic-gate } 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate int 254*0Sstevel@tonic-gate ftrace_stop(void) 255*0Sstevel@tonic-gate { 256*0Sstevel@tonic-gate int i, was_enabled = 0; 257*0Sstevel@tonic-gate 258*0Sstevel@tonic-gate if (ftrace_state & FTRACE_READY) { 259*0Sstevel@tonic-gate mutex_enter(&ftrace_lock); 260*0Sstevel@tonic-gate if (ftrace_state & FTRACE_ENABLED) { 261*0Sstevel@tonic-gate was_enabled = 1; 262*0Sstevel@tonic-gate for (i = 0; i < NCPU; i++) 263*0Sstevel@tonic-gate if (IS_CPU(i)) 264*0Sstevel@tonic-gate ftrace_cpu_stop(i); 265*0Sstevel@tonic-gate ftrace_state &= ~(FTRACE_ENABLED); 266*0Sstevel@tonic-gate } 267*0Sstevel@tonic-gate mutex_exit(&ftrace_lock); 268*0Sstevel@tonic-gate } 269*0Sstevel@tonic-gate return (was_enabled); 270*0Sstevel@tonic-gate } 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate void 273*0Sstevel@tonic-gate ftrace_0(char *str) 274*0Sstevel@tonic-gate { 275*0Sstevel@tonic-gate ftrace_record_t *r; 276*0Sstevel@tonic-gate struct cpu *cp = CPU; 277*0Sstevel@tonic-gate ftrace_data_t *ftd = &cp->cpu_ftrace; 278*0Sstevel@tonic-gate 279*0Sstevel@tonic-gate if (mutex_tryenter(&ftd->ftd_mutex) == 0) { 280*0Sstevel@tonic-gate if (CPU_ON_INTR(cp)) 281*0Sstevel@tonic-gate return; 282*0Sstevel@tonic-gate else 283*0Sstevel@tonic-gate mutex_enter(&ftd->ftd_mutex); 284*0Sstevel@tonic-gate } 285*0Sstevel@tonic-gate r = ftd->ftd_cur; 286*0Sstevel@tonic-gate r->ftr_event = str; 287*0Sstevel@tonic-gate r->ftr_thread = curthread; 288*0Sstevel@tonic-gate r->ftr_tick = gethrtime_unscaled(); 289*0Sstevel@tonic-gate r->ftr_caller = caller(); 290*0Sstevel@tonic-gate 291*0Sstevel@tonic-gate if (r++ == ftd->ftd_last) 292*0Sstevel@tonic-gate r = ftd->ftd_first; 293*0Sstevel@tonic-gate ftd->ftd_cur = r; 294*0Sstevel@tonic-gate mutex_exit(&ftd->ftd_mutex); 295*0Sstevel@tonic-gate } 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate void 298*0Sstevel@tonic-gate ftrace_1(char *str, ulong_t arg1) 299*0Sstevel@tonic-gate { 300*0Sstevel@tonic-gate ftrace_record_t *r; 301*0Sstevel@tonic-gate struct cpu *cp = CPU; 302*0Sstevel@tonic-gate ftrace_data_t *ftd = &cp->cpu_ftrace; 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate if (mutex_tryenter(&ftd->ftd_mutex) == 0) { 305*0Sstevel@tonic-gate if (CPU_ON_INTR(cp)) 306*0Sstevel@tonic-gate return; 307*0Sstevel@tonic-gate else 308*0Sstevel@tonic-gate mutex_enter(&ftd->ftd_mutex); 309*0Sstevel@tonic-gate } 310*0Sstevel@tonic-gate r = ftd->ftd_cur; 311*0Sstevel@tonic-gate r->ftr_event = str; 312*0Sstevel@tonic-gate r->ftr_thread = curthread; 313*0Sstevel@tonic-gate r->ftr_tick = gethrtime_unscaled(); 314*0Sstevel@tonic-gate r->ftr_caller = caller(); 315*0Sstevel@tonic-gate r->ftr_data1 = arg1; 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gate if (r++ == ftd->ftd_last) 318*0Sstevel@tonic-gate r = ftd->ftd_first; 319*0Sstevel@tonic-gate ftd->ftd_cur = r; 320*0Sstevel@tonic-gate mutex_exit(&ftd->ftd_mutex); 321*0Sstevel@tonic-gate } 322*0Sstevel@tonic-gate 323*0Sstevel@tonic-gate void 324*0Sstevel@tonic-gate ftrace_2(char *str, ulong_t arg1, ulong_t arg2) 325*0Sstevel@tonic-gate { 326*0Sstevel@tonic-gate ftrace_record_t *r; 327*0Sstevel@tonic-gate struct cpu *cp = CPU; 328*0Sstevel@tonic-gate ftrace_data_t *ftd = &cp->cpu_ftrace; 329*0Sstevel@tonic-gate 330*0Sstevel@tonic-gate if (mutex_tryenter(&ftd->ftd_mutex) == 0) { 331*0Sstevel@tonic-gate if (CPU_ON_INTR(cp)) 332*0Sstevel@tonic-gate return; 333*0Sstevel@tonic-gate else 334*0Sstevel@tonic-gate mutex_enter(&ftd->ftd_mutex); 335*0Sstevel@tonic-gate } 336*0Sstevel@tonic-gate r = ftd->ftd_cur; 337*0Sstevel@tonic-gate r->ftr_event = str; 338*0Sstevel@tonic-gate r->ftr_thread = curthread; 339*0Sstevel@tonic-gate r->ftr_tick = gethrtime_unscaled(); 340*0Sstevel@tonic-gate r->ftr_caller = caller(); 341*0Sstevel@tonic-gate r->ftr_data1 = arg1; 342*0Sstevel@tonic-gate r->ftr_data2 = arg2; 343*0Sstevel@tonic-gate 344*0Sstevel@tonic-gate if (r++ == ftd->ftd_last) 345*0Sstevel@tonic-gate r = ftd->ftd_first; 346*0Sstevel@tonic-gate ftd->ftd_cur = r; 347*0Sstevel@tonic-gate mutex_exit(&ftd->ftd_mutex); 348*0Sstevel@tonic-gate } 349*0Sstevel@tonic-gate 350*0Sstevel@tonic-gate void 351*0Sstevel@tonic-gate ftrace_3(char *str, ulong_t arg1, ulong_t arg2, ulong_t arg3) 352*0Sstevel@tonic-gate { 353*0Sstevel@tonic-gate ftrace_record_t *r; 354*0Sstevel@tonic-gate struct cpu *cp = CPU; 355*0Sstevel@tonic-gate ftrace_data_t *ftd = &cp->cpu_ftrace; 356*0Sstevel@tonic-gate 357*0Sstevel@tonic-gate if (mutex_tryenter(&ftd->ftd_mutex) == 0) { 358*0Sstevel@tonic-gate if (CPU_ON_INTR(cp)) 359*0Sstevel@tonic-gate return; 360*0Sstevel@tonic-gate else 361*0Sstevel@tonic-gate mutex_enter(&ftd->ftd_mutex); 362*0Sstevel@tonic-gate } 363*0Sstevel@tonic-gate r = ftd->ftd_cur; 364*0Sstevel@tonic-gate r->ftr_event = str; 365*0Sstevel@tonic-gate r->ftr_thread = curthread; 366*0Sstevel@tonic-gate r->ftr_tick = gethrtime_unscaled(); 367*0Sstevel@tonic-gate r->ftr_caller = caller(); 368*0Sstevel@tonic-gate r->ftr_data1 = arg1; 369*0Sstevel@tonic-gate r->ftr_data2 = arg2; 370*0Sstevel@tonic-gate r->ftr_data3 = arg3; 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate if (r++ == ftd->ftd_last) 373*0Sstevel@tonic-gate r = ftd->ftd_first; 374*0Sstevel@tonic-gate ftd->ftd_cur = r; 375*0Sstevel@tonic-gate mutex_exit(&ftd->ftd_mutex); 376*0Sstevel@tonic-gate } 377*0Sstevel@tonic-gate 378*0Sstevel@tonic-gate void 379*0Sstevel@tonic-gate ftrace_3_notick(char *str, ulong_t arg1, ulong_t arg2, ulong_t arg3) 380*0Sstevel@tonic-gate { 381*0Sstevel@tonic-gate ftrace_record_t *r; 382*0Sstevel@tonic-gate struct cpu *cp = CPU; 383*0Sstevel@tonic-gate ftrace_data_t *ftd = &cp->cpu_ftrace; 384*0Sstevel@tonic-gate 385*0Sstevel@tonic-gate if (mutex_tryenter(&ftd->ftd_mutex) == 0) { 386*0Sstevel@tonic-gate if (CPU_ON_INTR(cp)) 387*0Sstevel@tonic-gate return; 388*0Sstevel@tonic-gate else 389*0Sstevel@tonic-gate mutex_enter(&ftd->ftd_mutex); 390*0Sstevel@tonic-gate } 391*0Sstevel@tonic-gate r = ftd->ftd_cur; 392*0Sstevel@tonic-gate r->ftr_event = str; 393*0Sstevel@tonic-gate r->ftr_thread = curthread; 394*0Sstevel@tonic-gate r->ftr_tick = 0; 395*0Sstevel@tonic-gate r->ftr_caller = caller(); 396*0Sstevel@tonic-gate r->ftr_data1 = arg1; 397*0Sstevel@tonic-gate r->ftr_data2 = arg2; 398*0Sstevel@tonic-gate r->ftr_data3 = arg3; 399*0Sstevel@tonic-gate 400*0Sstevel@tonic-gate if (r++ == ftd->ftd_last) 401*0Sstevel@tonic-gate r = ftd->ftd_first; 402*0Sstevel@tonic-gate ftd->ftd_cur = r; 403*0Sstevel@tonic-gate mutex_exit(&ftd->ftd_mutex); 404*0Sstevel@tonic-gate } 405