kern_ktr.c revision 78784
165556Sjasone/* 265556Sjasone * Copyright (c) 2000 365556Sjasone * John Baldwin <jhb@FreeBSD.org>. All rights reserved. 465556Sjasone * 565556Sjasone * Redistribution and use in source and binary forms, with or without 665556Sjasone * modification, are permitted provided that the following conditions 765556Sjasone * are met: 865556Sjasone * 1. Redistributions of source code must retain the above copyright 965556Sjasone * notice, this list of conditions and the following disclaimer. 1065556Sjasone * 2. Redistributions in binary form must reproduce the above copyright 1165556Sjasone * notice, this list of conditions and the following disclaimer in the 1265556Sjasone * documentation and/or other materials provided with the distribution. 1365556Sjasone * 4. Neither the name of the author nor the names of any co-contributors 1465556Sjasone * may be used to endorse or promote products derived from this software 1565556Sjasone * without specific prior written permission. 1665556Sjasone * 1769012Sjhb * THIS SOFTWARE IS PROVIDED BY JOHN BALDWIN AND CONTRIBUTORS ``AS IS'' AND 1865556Sjasone * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1965556Sjasone * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2069012Sjhb * ARE DISCLAIMED. IN NO EVENT SHALL JOHN BALDWIN OR THE VOICES IN HIS HEAD 2165556Sjasone * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2265556Sjasone * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2365556Sjasone * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2465556Sjasone * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2565556Sjasone * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2665556Sjasone * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 2765556Sjasone * THE POSSIBILITY OF SUCH DAMAGE. 2865556Sjasone * 2965556Sjasone * $FreeBSD: head/sys/kern/kern_ktr.c 78784 2001-06-25 23:09:31Z jhb $ 3065556Sjasone */ 3165556Sjasone 3265556Sjasone/* 3368420Sjhb * This module holds the global variables used by KTR and the ktr_tracepoint() 3468420Sjhb * function that does the actual tracing. 3565556Sjasone */ 3665556Sjasone 3770035Sjhb#include "opt_ddb.h" 3868420Sjhb#include "opt_ktr.h" 3968420Sjhb 4070035Sjhb#include <sys/param.h> 4170035Sjhb#include <sys/cons.h> 4270705Sjhb#include <sys/kernel.h> 4365556Sjasone#include <sys/ktr.h> 4468420Sjhb#include <sys/libkern.h> 4565556Sjasone#include <sys/sysctl.h> 4668420Sjhb#include <sys/systm.h> 4778784Sjhb#include <sys/time.h> 4868584Sjhb#include <machine/globals.h> 4968420Sjhb#include <machine/stdarg.h> 5065556Sjasone 5170035Sjhb#include <ddb/ddb.h> 5270035Sjhb 5378784Sjhb#ifndef KTR_ENTRIES 5478784Sjhb#define KTR_ENTRIES 1024 5578784Sjhb#endif 5678784Sjhb 5768420Sjhb#ifndef KTR_MASK 5868420Sjhb#define KTR_MASK (KTR_GEN) 5968420Sjhb#endif 6068420Sjhb 6168420Sjhb#ifndef KTR_CPUMASK 6268420Sjhb#define KTR_CPUMASK (~0) 6368420Sjhb#endif 6468420Sjhb 6568420Sjhb#ifdef SMP 6670861Sjake#define KTR_CPU PCPU_GET(cpuid) 6768420Sjhb#else 6868420Sjhb#define KTR_CPU 0 6968420Sjhb#endif 7068420Sjhb 7165556Sjasone#ifdef KTR_EXTEND 7270705Sjhb#define KTR_EXTEND_DEFAULT 1 7370705Sjhb#else 7470705Sjhb#define KTR_EXTEND_DEFAULT 0 7570705Sjhb#endif 7670705Sjhb 7770705Sjhb#ifdef KTR_VERBOSE 7870705Sjhb#define KTR_VERBOSE_DEFAULT 1 7970705Sjhb#else 8070705Sjhb#define KTR_VERBOSE_DEFAULT 0 8170705Sjhb#endif 8270705Sjhb 8370705SjhbSYSCTL_NODE(_debug, OID_AUTO, ktr, CTLFLAG_RD, 0, "KTR options"); 8470705Sjhb 8565556Sjasone/* 8665556Sjasone * This variable is used only by gdb to work out what fields are in 8765556Sjasone * ktr_entry. 8865556Sjasone */ 8970705Sjhbint ktr_extend = KTR_EXTEND_DEFAULT; 9070705SjhbSYSCTL_INT(_debug_ktr, OID_AUTO, extend, CTLFLAG_RD, &ktr_extend, 0, ""); 9165556Sjasone 9277843Speterint ktr_cpumask = KTR_CPUMASK; 9377900SpeterTUNABLE_INT("debug.ktr.cpumask", &ktr_cpumask); 9470705SjhbSYSCTL_INT(_debug_ktr, OID_AUTO, cpumask, CTLFLAG_RW, &ktr_cpumask, 0, ""); 9565556Sjasone 9677843Speterint ktr_mask = KTR_MASK; 9777900SpeterTUNABLE_INT("debug.ktr.mask", &ktr_mask); 9870705SjhbSYSCTL_INT(_debug_ktr, OID_AUTO, mask, CTLFLAG_RW, &ktr_mask, 0, ""); 9965556Sjasone 10065556Sjasoneint ktr_entries = KTR_ENTRIES; 10170705SjhbSYSCTL_INT(_debug_ktr, OID_AUTO, entries, CTLFLAG_RD, &ktr_entries, 0, ""); 10265556Sjasone 10365556Sjasonevolatile int ktr_idx = 0; 10465556Sjasonestruct ktr_entry ktr_buf[KTR_ENTRIES]; 10568420Sjhb 10677843Speterint ktr_verbose = KTR_VERBOSE_DEFAULT; 10777900SpeterTUNABLE_INT("debug.ktr.verbose", &ktr_verbose); 10870705SjhbSYSCTL_INT(_debug_ktr, OID_AUTO, verbose, CTLFLAG_RW, &ktr_verbose, 0, ""); 10968420Sjhb 11068420Sjhb#ifdef KTR 11168420Sjhb#ifdef KTR_EXTEND 11268420Sjhbvoid 11372761Sjhbktr_tracepoint(u_int mask, const char *filename, u_int line, 11472761Sjhb const char *format, ...) 11568420Sjhb#else 11668420Sjhbvoid 11772761Sjhbktr_tracepoint(u_int mask, const char *format, u_long arg1, u_long arg2, 11872761Sjhb u_long arg3, u_long arg4, u_long arg5) 11968420Sjhb#endif 12068420Sjhb{ 12168420Sjhb struct ktr_entry *entry; 12274903Sjhb int newindex, saveindex; 12374903Sjhb critical_t savecrit; 12468420Sjhb#ifdef KTR_EXTEND 12568420Sjhb va_list ap; 12668420Sjhb#endif 12768420Sjhb 12869880Sjhb if (panicstr) 12969880Sjhb return; 13068420Sjhb if ((ktr_mask & mask) == 0) 13168420Sjhb return; 13278784Sjhb savecrit = critical_enter(); 13378784Sjhb if (((1 << KTR_CPU) & ktr_cpumask) == 0) { 13478784Sjhb critical_exit(savecrit); 13568420Sjhb return; 13678784Sjhb } 13778784Sjhb atomic_clear_int(&ktr_cpumask, 1 << KTR_CPU); 13868420Sjhb do { 13968420Sjhb saveindex = ktr_idx; 14068420Sjhb newindex = (saveindex + 1) & (KTR_ENTRIES - 1); 14168420Sjhb } while (atomic_cmpset_rel_int(&ktr_idx, saveindex, newindex) == 0); 14268420Sjhb entry = &ktr_buf[saveindex]; 14378784Sjhb /* 14478784Sjhb * XXX: The ktr_cpumask atomic ops should make this unnecessary. 14578784Sjhb */ 14678784Sjhb if ((ktr_mask & (KTR_LOCK | KTR_WITNESS)) != 0) 14770464Sgrog getnanotime(&entry->ktr_tv); 14870464Sgrog else 14970464Sgrog nanotime(&entry->ktr_tv); 15078784Sjhb atomic_set_int(&ktr_cpumask, 1 << KTR_CPU); 15178784Sjhb entry->ktr_cpu = KTR_CPU; 15278784Sjhb critical_exit(savecrit); 15368420Sjhb#ifdef KTR_EXTEND 15472761Sjhb entry->ktr_filename = filename; 15568420Sjhb entry->ktr_line = line; 15668420Sjhb va_start(ap, format); 15768420Sjhb vsnprintf(entry->ktr_desc, KTRDESCSIZE, format, ap); 15868420Sjhb va_end(ap); 15968420Sjhb if (ktr_verbose) { 16068782Sjhb#ifdef SMP 16168782Sjhb printf("cpu%d ", entry->ktr_cpu); 16268782Sjhb#endif 16368782Sjhb if (ktr_verbose > 1) 16468782Sjhb printf("%s.%d\t", entry->ktr_filename, entry->ktr_line); 16568420Sjhb va_start(ap, format); 16668420Sjhb vprintf(format, ap); 16768420Sjhb printf("\n"); 16868420Sjhb va_end(ap); 16968420Sjhb } 17068420Sjhb#else 17168420Sjhb entry->ktr_desc = format; 17268420Sjhb entry->ktr_parm1 = arg1; 17368420Sjhb entry->ktr_parm2 = arg2; 17468420Sjhb entry->ktr_parm3 = arg3; 17568420Sjhb entry->ktr_parm4 = arg4; 17668420Sjhb entry->ktr_parm5 = arg5; 17768420Sjhb#endif 17868420Sjhb} 17970035Sjhb 18070035Sjhb#ifdef DDB 18170035Sjhb 18270035Sjhbstruct tstate { 18370035Sjhb int cur; 18470035Sjhb int first; 18570035Sjhb}; 18670035Sjhbstatic struct tstate tstate; 18770035Sjhbstatic int db_ktr_verbose; 18870035Sjhbstatic int db_mach_vtrace(void); 18970035Sjhb 19072755Sjhb#define NUM_LINES_PER_PAGE 18 19172755Sjhb 19272755SjhbDB_SHOW_COMMAND(ktr, db_ktr_all) 19370035Sjhb{ 19472755Sjhb int c, lines; 19570035Sjhb 19672755Sjhb lines = NUM_LINES_PER_PAGE; 19770035Sjhb tstate.cur = (ktr_idx - 1) & (KTR_ENTRIES - 1); 19870035Sjhb tstate.first = -1; 19970035Sjhb if (strcmp(modif, "v") == 0) 20070035Sjhb db_ktr_verbose = 1; 20170035Sjhb else 20270035Sjhb db_ktr_verbose = 0; 20372755Sjhb while (db_mach_vtrace()) 20472755Sjhb if (--lines == 0) { 20572755Sjhb db_printf("--More--"); 20672755Sjhb c = cngetc(); 20772755Sjhb db_printf("\r"); 20872755Sjhb switch (c) { 20972755Sjhb case '\n': /* one more line */ 21072755Sjhb lines = 1; 21172755Sjhb break; 21272755Sjhb case ' ': /* one more page */ 21372755Sjhb lines = NUM_LINES_PER_PAGE; 21472755Sjhb break; 21572755Sjhb default: 21672755Sjhb db_printf("\n"); 21772755Sjhb return; 21872755Sjhb } 21972755Sjhb } 22070035Sjhb} 22170035Sjhb 22270035Sjhbstatic int 22370035Sjhbdb_mach_vtrace(void) 22470035Sjhb{ 22570035Sjhb struct ktr_entry *kp; 22670035Sjhb 22770035Sjhb if (tstate.cur == tstate.first) { 22870035Sjhb db_printf("--- End of trace buffer ---\n"); 22970035Sjhb return (0); 23070035Sjhb } 23170035Sjhb kp = &ktr_buf[tstate.cur]; 23270035Sjhb 23370035Sjhb /* Skip over unused entries. */ 23470035Sjhb#ifdef KTR_EXTEND 23572755Sjhb if (kp->ktr_desc[0] == '\0') { 23670035Sjhb#else 23772755Sjhb if (kp->ktr_desc == NULL) { 23870035Sjhb#endif 23972755Sjhb db_printf("--- End of trace buffer ---\n"); 24072755Sjhb return (0); 24172755Sjhb } 24272755Sjhb db_printf("%d: ", tstate.cur); 24372755Sjhb if (db_ktr_verbose) 24472755Sjhb db_printf("%4ld.%06ld ", (long)kp->ktr_tv.tv_sec, 24572755Sjhb kp->ktr_tv.tv_nsec / 1000); 24670035Sjhb#ifdef KTR_EXTEND 24770035Sjhb#ifdef SMP 24872755Sjhb db_printf("cpu%d ", kp->ktr_cpu); 24970035Sjhb#endif 25072755Sjhb if (db_ktr_verbose) 25172755Sjhb db_printf("%s.%d\t", kp->ktr_filename, kp->ktr_line); 25272755Sjhb db_printf("%s", kp->ktr_desc); 25370035Sjhb#else 25472755Sjhb db_printf(kp->ktr_desc, kp->ktr_parm1, kp->ktr_parm2, kp->ktr_parm3, 25572755Sjhb kp->ktr_parm4, kp->ktr_parm5); 25670035Sjhb#endif 25772755Sjhb db_printf("\n"); 25870035Sjhb 25970035Sjhb if (tstate.first == -1) 26070035Sjhb tstate.first = tstate.cur; 26170035Sjhb 26270035Sjhb if (--tstate.cur < 0) 26370035Sjhb tstate.cur = KTR_ENTRIES - 1; 26470035Sjhb 26570035Sjhb return (1); 26670035Sjhb} 26770035Sjhb 26870035Sjhb#endif /* DDB */ 26968420Sjhb#endif /* KTR */ 270