The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_ktr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2000 John Baldwin <jhb@FreeBSD.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 /*
   28  * This module holds the global variables used by KTR and the ktr_tracepoint()
   29  * function that does the actual tracing.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD$");
   34 
   35 #include "opt_ddb.h"
   36 #include "opt_ktr.h"
   37 #include "opt_alq.h"
   38 
   39 #include <sys/param.h>
   40 #include <sys/queue.h>
   41 #include <sys/alq.h>
   42 #include <sys/cons.h>
   43 #include <sys/cpuset.h>
   44 #include <sys/kernel.h>
   45 #include <sys/ktr.h>
   46 #include <sys/libkern.h>
   47 #include <sys/proc.h>
   48 #include <sys/sysctl.h>
   49 #include <sys/systm.h>
   50 #include <sys/time.h>
   51 
   52 #include <machine/cpu.h>
   53 #ifdef __sparc64__
   54 #include <machine/ktr.h>
   55 #endif
   56 
   57 #ifdef DDB
   58 #include <ddb/ddb.h>
   59 #include <ddb/db_output.h>
   60 #endif
   61 
   62 #ifndef KTR_ENTRIES
   63 #define KTR_ENTRIES     1024
   64 #endif
   65 
   66 #ifndef KTR_MASK
   67 #define KTR_MASK        (0)
   68 #endif
   69 
   70 #ifndef KTR_TIME
   71 #define KTR_TIME        get_cyclecount()
   72 #endif
   73 
   74 #ifndef KTR_CPU
   75 #define KTR_CPU         PCPU_GET(cpuid)
   76 #endif
   77 
   78 FEATURE(ktr, "Kernel support for KTR kernel tracing facility");
   79 
   80 static SYSCTL_NODE(_debug, OID_AUTO, ktr, CTLFLAG_RD, 0, "KTR options");
   81 
   82 int     ktr_mask = KTR_MASK;
   83 TUNABLE_INT("debug.ktr.mask", &ktr_mask);
   84 SYSCTL_INT(_debug_ktr, OID_AUTO, mask, CTLFLAG_RW,
   85     &ktr_mask, 0, "Bitmask of KTR event classes for which logging is enabled");
   86 
   87 int     ktr_compile = KTR_COMPILE;
   88 SYSCTL_INT(_debug_ktr, OID_AUTO, compile, CTLFLAG_RD,
   89     &ktr_compile, 0, "Bitmask of KTR event classes compiled into the kernel");
   90 
   91 int     ktr_entries = KTR_ENTRIES;
   92 SYSCTL_INT(_debug_ktr, OID_AUTO, entries, CTLFLAG_RD,
   93     &ktr_entries, 0, "Number of entries in the KTR buffer");
   94 
   95 int     ktr_version = KTR_VERSION;
   96 SYSCTL_INT(_debug_ktr, OID_AUTO, version, CTLFLAG_RD,
   97     &ktr_version, 0, "Version of the KTR interface");
   98 
   99 cpuset_t ktr_cpumask;
  100 static char ktr_cpumask_str[CPUSETBUFSIZ];
  101 TUNABLE_STR("debug.ktr.cpumask", ktr_cpumask_str, sizeof(ktr_cpumask_str));
  102 
  103 static void
  104 ktr_cpumask_initializer(void *dummy __unused)
  105 {
  106 
  107         CPU_FILL(&ktr_cpumask);
  108 #ifdef KTR_CPUMASK
  109         if (cpusetobj_strscan(&ktr_cpumask, KTR_CPUMASK) == -1)
  110                 CPU_FILL(&ktr_cpumask);
  111 #endif
  112 
  113         /*
  114          * TUNABLE_STR() runs with SI_ORDER_MIDDLE priority, thus it must be
  115          * already set, if necessary.
  116          */
  117         if (ktr_cpumask_str[0] != '\0' &&
  118             cpusetobj_strscan(&ktr_cpumask, ktr_cpumask_str) == -1)
  119                 CPU_FILL(&ktr_cpumask);
  120 }
  121 SYSINIT(ktr_cpumask_initializer, SI_SUB_TUNABLES, SI_ORDER_ANY,
  122     ktr_cpumask_initializer, NULL);
  123 
  124 static int
  125 sysctl_debug_ktr_cpumask(SYSCTL_HANDLER_ARGS)
  126 {
  127         char lktr_cpumask_str[CPUSETBUFSIZ];
  128         cpuset_t imask;
  129         int error;
  130 
  131         cpusetobj_strprint(lktr_cpumask_str, &ktr_cpumask);
  132         error = sysctl_handle_string(oidp, lktr_cpumask_str,
  133             sizeof(lktr_cpumask_str), req);
  134         if (error != 0 || req->newptr == NULL)
  135                 return (error);
  136         if (cpusetobj_strscan(&imask, lktr_cpumask_str) == -1)
  137                 return (EINVAL);
  138         CPU_COPY(&imask, &ktr_cpumask);
  139 
  140         return (error);
  141 }
  142 SYSCTL_PROC(_debug_ktr, OID_AUTO, cpumask,
  143     CTLFLAG_RW | CTLFLAG_MPSAFE | CTLTYPE_STRING, NULL, 0,
  144     sysctl_debug_ktr_cpumask, "S",
  145     "Bitmask of CPUs on which KTR logging is enabled");
  146 
  147 volatile int    ktr_idx = 0;
  148 struct  ktr_entry ktr_buf[KTR_ENTRIES];
  149 
  150 static int
  151 sysctl_debug_ktr_clear(SYSCTL_HANDLER_ARGS)
  152 {
  153         int clear, error;
  154 
  155         clear = 0;
  156         error = sysctl_handle_int(oidp, &clear, 0, req);
  157         if (error || !req->newptr)
  158                 return (error);
  159 
  160         if (clear) {
  161                 bzero(ktr_buf, sizeof(ktr_buf));
  162                 ktr_idx = 0;
  163         }
  164 
  165         return (error);
  166 }
  167 SYSCTL_PROC(_debug_ktr, OID_AUTO, clear, CTLTYPE_INT|CTLFLAG_RW, 0, 0,
  168     sysctl_debug_ktr_clear, "I", "Clear KTR Buffer");
  169 
  170 #ifdef KTR_VERBOSE
  171 int     ktr_verbose = KTR_VERBOSE;
  172 TUNABLE_INT("debug.ktr.verbose", &ktr_verbose);
  173 SYSCTL_INT(_debug_ktr, OID_AUTO, verbose, CTLFLAG_RW, &ktr_verbose, 0, "");
  174 #endif
  175 
  176 #ifdef KTR_ALQ
  177 struct alq *ktr_alq;
  178 char    ktr_alq_file[MAXPATHLEN] = "/tmp/ktr.out";
  179 int     ktr_alq_cnt = 0;
  180 int     ktr_alq_depth = KTR_ENTRIES;
  181 int     ktr_alq_enabled = 0;
  182 int     ktr_alq_failed = 0;
  183 int     ktr_alq_max = 0;
  184 
  185 SYSCTL_INT(_debug_ktr, OID_AUTO, alq_max, CTLFLAG_RW, &ktr_alq_max, 0,
  186     "Maximum number of entries to write");
  187 SYSCTL_INT(_debug_ktr, OID_AUTO, alq_cnt, CTLFLAG_RD, &ktr_alq_cnt, 0,
  188     "Current number of written entries");
  189 SYSCTL_INT(_debug_ktr, OID_AUTO, alq_failed, CTLFLAG_RD, &ktr_alq_failed, 0,
  190     "Number of times we overran the buffer");
  191 SYSCTL_INT(_debug_ktr, OID_AUTO, alq_depth, CTLFLAG_RW, &ktr_alq_depth, 0,
  192     "Number of items in the write buffer");
  193 SYSCTL_STRING(_debug_ktr, OID_AUTO, alq_file, CTLFLAG_RW, ktr_alq_file,
  194     sizeof(ktr_alq_file), "KTR logging file");
  195 
  196 static int
  197 sysctl_debug_ktr_alq_enable(SYSCTL_HANDLER_ARGS)
  198 {
  199         int error;
  200         int enable;
  201 
  202         enable = ktr_alq_enabled;
  203 
  204         error = sysctl_handle_int(oidp, &enable, 0, req);
  205         if (error || !req->newptr)
  206                 return (error);
  207 
  208         if (enable) {
  209                 if (ktr_alq_enabled)
  210                         return (0);
  211                 error = alq_open(&ktr_alq, (const char *)ktr_alq_file,
  212                     req->td->td_ucred, ALQ_DEFAULT_CMODE,
  213                     sizeof(struct ktr_entry), ktr_alq_depth);
  214                 if (error == 0) {
  215                         ktr_alq_cnt = 0;
  216                         ktr_alq_failed = 0;
  217                         ktr_alq_enabled = 1;
  218                 }
  219         } else {
  220                 if (ktr_alq_enabled == 0)
  221                         return (0);
  222                 ktr_alq_enabled = 0;
  223                 alq_close(ktr_alq);
  224                 ktr_alq = NULL;
  225         }
  226 
  227         return (error);
  228 }
  229 SYSCTL_PROC(_debug_ktr, OID_AUTO, alq_enable,
  230     CTLTYPE_INT|CTLFLAG_RW, 0, 0, sysctl_debug_ktr_alq_enable,
  231     "I", "Enable KTR logging");
  232 #endif
  233 
  234 void
  235 ktr_tracepoint(u_int mask, const char *file, int line, const char *format,
  236     u_long arg1, u_long arg2, u_long arg3, u_long arg4, u_long arg5,
  237     u_long arg6)
  238 {
  239         struct ktr_entry *entry;
  240 #ifdef KTR_ALQ
  241         struct ale *ale = NULL;
  242 #endif
  243         int newindex, saveindex;
  244 #if defined(KTR_VERBOSE) || defined(KTR_ALQ)
  245         struct thread *td;
  246 #endif
  247         int cpu;
  248 
  249         if (panicstr)
  250                 return;
  251         if ((ktr_mask & mask) == 0)
  252                 return;
  253         cpu = KTR_CPU;
  254         if (!CPU_ISSET(cpu, &ktr_cpumask))
  255                 return;
  256 #if defined(KTR_VERBOSE) || defined(KTR_ALQ)
  257         td = curthread;
  258         if (td->td_pflags & TDP_INKTR)
  259                 return;
  260         td->td_pflags |= TDP_INKTR;
  261 #endif
  262 #ifdef KTR_ALQ
  263         if (ktr_alq_enabled) {
  264                 if (td->td_critnest == 0 &&
  265                     (td->td_flags & TDF_IDLETD) == 0 &&
  266                     td != ald_thread) {
  267                         if (ktr_alq_max && ktr_alq_cnt > ktr_alq_max)
  268                                 goto done;
  269                         if ((ale = alq_get(ktr_alq, ALQ_NOWAIT)) == NULL) {
  270                                 ktr_alq_failed++;
  271                                 goto done;
  272                         }
  273                         ktr_alq_cnt++;
  274                         entry = (struct ktr_entry *)ale->ae_data;
  275                 } else {
  276                         goto done;
  277                 }
  278         } else
  279 #endif
  280         {
  281                 do {
  282                         saveindex = ktr_idx;
  283                         newindex = (saveindex + 1) % KTR_ENTRIES;
  284                 } while (atomic_cmpset_rel_int(&ktr_idx, saveindex, newindex) == 0);
  285                 entry = &ktr_buf[saveindex];
  286         }
  287         entry->ktr_timestamp = KTR_TIME;
  288         entry->ktr_cpu = cpu;
  289         entry->ktr_thread = curthread;
  290         if (file != NULL)
  291                 while (strncmp(file, "../", 3) == 0)
  292                         file += 3;
  293         entry->ktr_file = file;
  294         entry->ktr_line = line;
  295 #ifdef KTR_VERBOSE
  296         if (ktr_verbose) {
  297 #ifdef SMP
  298                 printf("cpu%d ", cpu);
  299 #endif
  300                 if (ktr_verbose > 1) {
  301                         printf("%s.%d\t", entry->ktr_file,
  302                             entry->ktr_line);
  303                 }
  304                 printf(format, arg1, arg2, arg3, arg4, arg5, arg6);
  305                 printf("\n");
  306         }
  307 #endif
  308         entry->ktr_desc = format;
  309         entry->ktr_parms[0] = arg1;
  310         entry->ktr_parms[1] = arg2;
  311         entry->ktr_parms[2] = arg3;
  312         entry->ktr_parms[3] = arg4;
  313         entry->ktr_parms[4] = arg5;
  314         entry->ktr_parms[5] = arg6;
  315 #ifdef KTR_ALQ
  316         if (ktr_alq_enabled && ale)
  317                 alq_post(ktr_alq, ale);
  318 done:
  319 #endif
  320 #if defined(KTR_VERBOSE) || defined(KTR_ALQ)
  321         td->td_pflags &= ~TDP_INKTR;
  322 #endif
  323 }
  324 
  325 #ifdef DDB
  326 
  327 struct tstate {
  328         int     cur;
  329         int     first;
  330 };
  331 static  struct tstate tstate;
  332 static  int db_ktr_verbose;
  333 static  int db_mach_vtrace(void);
  334 
  335 DB_SHOW_COMMAND(ktr, db_ktr_all)
  336 {
  337         
  338         tstate.cur = (ktr_idx - 1) % KTR_ENTRIES;
  339         tstate.first = -1;
  340         db_ktr_verbose = 0;
  341         db_ktr_verbose |= (index(modif, 'v') != NULL) ? 2 : 0;
  342         db_ktr_verbose |= (index(modif, 'V') != NULL) ? 1 : 0; /* just timestap please */
  343         if (index(modif, 'a') != NULL) {
  344                 db_disable_pager();
  345                 while (cncheckc() != -1)
  346                         if (db_mach_vtrace() == 0)
  347                                 break;
  348         } else {
  349                 while (!db_pager_quit)
  350                         if (db_mach_vtrace() == 0)
  351                                 break;
  352         }
  353 }
  354 
  355 static int
  356 db_mach_vtrace(void)
  357 {
  358         struct ktr_entry        *kp;
  359 
  360         if (tstate.cur == tstate.first) {
  361                 db_printf("--- End of trace buffer ---\n");
  362                 return (0);
  363         }
  364         kp = &ktr_buf[tstate.cur];
  365 
  366         /* Skip over unused entries. */
  367         if (kp->ktr_desc == NULL) {
  368                 db_printf("--- End of trace buffer ---\n");
  369                 return (0);
  370         }
  371         db_printf("%d (%p", tstate.cur, kp->ktr_thread);
  372 #ifdef SMP
  373         db_printf(":cpu%d", kp->ktr_cpu);
  374 #endif
  375         db_printf(")");
  376         if (db_ktr_verbose >= 1) {
  377                 db_printf(" %10.10lld", (long long)kp->ktr_timestamp);
  378         }
  379         if (db_ktr_verbose >= 2) {
  380                 db_printf(" %s.%d", kp->ktr_file, kp->ktr_line);
  381         }
  382         db_printf(": ");
  383         db_printf(kp->ktr_desc, kp->ktr_parms[0], kp->ktr_parms[1],
  384             kp->ktr_parms[2], kp->ktr_parms[3], kp->ktr_parms[4],
  385             kp->ktr_parms[5]);
  386         db_printf("\n");
  387 
  388         if (tstate.first == -1)
  389                 tstate.first = tstate.cur;
  390 
  391         if (--tstate.cur < 0)
  392                 tstate.cur = KTR_ENTRIES - 1;
  393 
  394         return (1);
  395 }
  396 
  397 #endif  /* DDB */

Cache object: 6d81e3dc7940e822af7bb73ead9f46b5


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.