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_boottrace.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2008-2022 NetApp, Inc.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/param.h>
   28 #include <sys/systm.h>
   29 #include <sys/boottrace.h>
   30 #include <sys/kernel.h>
   31 #include <sys/malloc.h>
   32 #include <sys/pcpu.h>
   33 #include <sys/proc.h>
   34 #include <sys/resourcevar.h>
   35 #include <sys/sbuf.h>
   36 #include <sys/syscallsubr.h>
   37 #include <sys/sysctl.h>
   38 #include <sys/time.h>
   39 
   40 #include <machine/stdarg.h>
   41 
   42 #define dprintf(fmt, ...)                                               \
   43         do {                                                            \
   44                 if (dotrace_debugging)                                  \
   45                         printf(fmt, ##__VA_ARGS__);                     \
   46         } while (0);
   47 
   48 static MALLOC_DEFINE(M_BOOTTRACE, "boottrace", "memory for boot tracing");
   49 
   50 #define BT_TABLE_DEFSIZE        3000
   51 #define BT_TABLE_RUNSIZE        2000
   52 #define BT_TABLE_SHTSIZE        1000
   53 #define BT_TABLE_MINSIZE        500
   54 
   55 /*
   56  * Boot-time & shutdown-time event.
   57  */
   58 struct bt_event {
   59         uint64_t tsc;                   /* Timestamp */
   60         uint64_t tick;                  /* Kernel tick */
   61         uint64_t cputime;               /* Microseconds of process CPU time */
   62         uint32_t cpuid;                 /* CPU on which the event ran */
   63         uint32_t inblock;               /* # of blocks in */
   64         uint32_t oublock;               /* # of blocks out */
   65         pid_t pid;                      /* Current PID */
   66         char name[BT_EVENT_NAMELEN];    /* Event name */
   67         char tdname[BT_EVENT_TDNAMELEN]; /* Thread name */
   68 };
   69 
   70 struct bt_table {
   71         uint32_t size;                  /* Trace table size */
   72         uint32_t curr;                  /* Trace entry to use */
   73         uint32_t wrap;                  /* Wrap-around, instead of dropping */
   74         uint32_t drops_early;           /* Trace entries dropped before init */
   75         uint32_t drops_full;            /* Trace entries dropped after full */
   76         struct bt_event *table;
   77 };
   78 
   79 /* Boot-time tracing */
   80 static struct bt_table bt;
   81 
   82 /* Run-time tracing */
   83 static struct bt_table rt;
   84 
   85 /* Shutdown-time tracing */
   86 static struct bt_table st;
   87 
   88 /* Set when system boot is complete, and we've switched to runtime tracing. */
   89 static bool bootdone;
   90 
   91 /* Set when system shutdown has started. */
   92 static bool shutdown;
   93 
   94 /* Turn on dotrace() debug logging to console. */
   95 static bool dotrace_debugging;
   96 TUNABLE_BOOL("debug.boottrace.dotrace_debugging", &dotrace_debugging);
   97 
   98 /* Trace kernel events */
   99 static bool dotrace_kernel = true;
  100 TUNABLE_BOOL("kern.boottrace.dotrace_kernel", &dotrace_kernel);
  101 
  102 /* Trace userspace events */
  103 static bool dotrace_user = true;
  104 TUNABLE_BOOL("kern.boottrace.dotrace_user", &dotrace_user);
  105 
  106 static int sysctl_log(SYSCTL_HANDLER_ARGS);
  107 static int sysctl_boottrace(SYSCTL_HANDLER_ARGS);
  108 static int sysctl_runtrace(SYSCTL_HANDLER_ARGS);
  109 static int sysctl_shuttrace(SYSCTL_HANDLER_ARGS);
  110 static int sysctl_boottrace_reset(SYSCTL_HANDLER_ARGS);
  111 
  112 SYSCTL_NODE(_kern, OID_AUTO, boottrace, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
  113     "boottrace statistics");
  114 
  115 SYSCTL_PROC(_kern_boottrace, OID_AUTO, log,
  116     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE | CTLFLAG_SKIP,
  117     0, 0, sysctl_log, "A",
  118     "Print a log of the boottrace trace data");
  119 SYSCTL_PROC(_kern_boottrace, OID_AUTO, boottrace,
  120     CTLTYPE_STRING | CTLFLAG_WR | CTLFLAG_MPSAFE,
  121     0, 0, sysctl_boottrace, "A",
  122     "Capture a boot-time trace event");
  123 SYSCTL_PROC(_kern_boottrace, OID_AUTO, runtrace,
  124     CTLTYPE_STRING | CTLFLAG_WR | CTLFLAG_MPSAFE,
  125     0, 0, sysctl_runtrace, "A",
  126     "Capture a run-time trace event");
  127 SYSCTL_PROC(_kern_boottrace, OID_AUTO, shuttrace,
  128     CTLTYPE_STRING | CTLFLAG_WR | CTLFLAG_MPSAFE,
  129     0, 0, sysctl_shuttrace, "A",
  130     "Capture a shutdown-time trace event");
  131 SYSCTL_PROC(_kern_boottrace, OID_AUTO, reset,
  132     CTLTYPE_INT | CTLFLAG_WR | CTLFLAG_MPSAFE,
  133     0, 0, sysctl_boottrace_reset, "A",
  134     "Reset run-time tracing table");
  135 
  136 /*
  137  * Global enable.
  138  */
  139 bool __read_mostly boottrace_enabled = false;
  140 SYSCTL_BOOL(_kern_boottrace, OID_AUTO, enabled, CTLFLAG_RDTUN,
  141     &boottrace_enabled, 0,
  142     "Boot-time and shutdown-time tracing enabled");
  143 
  144 /*
  145  * Enable dumping of the shutdown trace entries to console.
  146  */
  147 bool shutdown_trace = false;
  148 SYSCTL_BOOL(_kern_boottrace, OID_AUTO, shutdown_trace, CTLFLAG_RWTUN,
  149    &shutdown_trace, 0,
  150    "Enable kernel shutdown tracing to the console");
  151 
  152 /*
  153  * Set the delta threshold (ms) below which events are ignored, used in
  154  * determining what to dump to the console.
  155  */
  156 static int shutdown_trace_threshold;
  157 SYSCTL_INT(_kern_boottrace, OID_AUTO, shutdown_trace_threshold, CTLFLAG_RWTUN,
  158    &shutdown_trace_threshold, 0,
  159    "Tracing threshold (ms) below which tracing is ignored");
  160 
  161 /*
  162  * Dump a trace to buffer or if buffer is NULL to console.
  163  *
  164  * Non-zero delta_threshold selectively prints entries based on delta
  165  * with current and previous entry. Otherwise, delta_threshold of 0
  166  * prints every trace entry and delta.
  167  *
  168  * Output something like this:
  169  *
  170  * CPU      msecs      delta process                  event
  171  *  11 1228262715          0 init                     shutdown pre sync begin
  172  *   3 1228265622       2907 init                     shutdown pre sync complete
  173  *   3 1228265623          0 init                     shutdown turned swap off
  174  *  18 1228266466        843 init                     shutdown unmounted all filesystems
  175  *
  176  * How to interpret:
  177  *
  178  * delta column represents the time in milliseconds between this event and the previous.
  179  * Usually that means you can take the previous event, current event, match them
  180  * up in the code, and whatever lies between is the culprit taking time.
  181  *
  182  * For example, above: Pre-Sync is taking 2907ms, and something between swap and unmount
  183  * filesystems is taking 843 milliseconds.
  184  *
  185  * An event with a delta of 0 are 'landmark' events that simply exist in the output
  186  * for the developer to know where the time measurement begins. The 0 is an arbitrary
  187  * number that can effectively be ignored.
  188  */
  189 #define BTC_DELTA_PRINT(bte, msecs, delta) do {                         \
  190         if (sbp) {                                                      \
  191                 sbuf_printf(sbp, fmt, (bte)->cpuid, msecs, delta,       \
  192                     (bte)->tdname, (bte)->name, (bte)->pid,             \
  193                     (bte)->cputime / 1000000,                           \
  194                     ((bte)->cputime % 1000000) / 10000,                 \
  195                     (bte)->inblock, (bte)->oublock);                    \
  196         } else {                                                        \
  197                 printf(fmt, (bte)->cpuid, msecs, delta,                 \
  198                     (bte)->tdname, (bte)->name, (bte)->pid,             \
  199                     (bte)->cputime / 1000000,                           \
  200                     ((bte)->cputime % 1000000) / 10000,                 \
  201                     (bte)->inblock, (bte)->oublock);                    \
  202         }                                                               \
  203 } while (0)
  204 
  205 /*
  206  * Print the trace entries to the message buffer, or to an sbuf, if provided.
  207  *
  208  * Entries with a difference less than dthres will not be printed.
  209  */
  210 static void
  211 boottrace_display(struct sbuf *sbp, struct bt_table *btp, uint64_t dthres)
  212 {
  213         struct bt_event *evtp;
  214         struct bt_event *last_evtp;
  215         uint64_t msecs;
  216         uint64_t first_msecs;
  217         uint64_t last_msecs;
  218         uint64_t dmsecs;
  219         uint64_t last_dmsecs;
  220         uint64_t total_dmsecs;
  221         uint32_t i;
  222         uint32_t curr;
  223         const char *fmt     = "%3u %10llu %10llu %-24s %-40s %5d %4d.%02d %5u %5u\n";
  224         const char *hdr_fmt = "\n\n%3s %10s %10s %-24s %-40s %5s %6s %5s %5s\n";
  225         bool printed;
  226         bool last_printed;
  227 
  228         /* Print the header */
  229         if (sbp != NULL)
  230                 sbuf_printf(sbp, hdr_fmt,
  231                     "CPU", "msecs", "delta", "process",
  232                     "event", "PID", "CPUtime", "IBlks", "OBlks");
  233         else
  234                 printf(hdr_fmt,
  235                     "CPU", "msecs", "delta", "process",
  236                     "event", "PID", "CPUtime", "IBlks", "OBlks");
  237 
  238         first_msecs = 0;
  239         last_evtp = NULL;
  240         last_msecs = 0;
  241         last_dmsecs = 0;
  242         last_printed = false;
  243         i = curr = btp->curr;
  244 
  245         do {
  246                 evtp = &btp->table[i];
  247                 if (evtp->tsc == 0)
  248                         goto next;
  249 
  250                 msecs = cputick2usec(evtp->tick) / 1000;
  251                 dmsecs = (last_msecs != 0 && msecs > last_msecs) ?
  252                     msecs - last_msecs : 0;
  253                 printed = false;
  254 
  255                 /*
  256                  * If a threshold is defined, start filtering events by the
  257                  * delta of msecs.
  258                  */
  259                 if (dthres != 0 && (dmsecs > dthres)) {
  260                         /*
  261                          * Print the previous entry as a landmark, even if it
  262                          * falls below the threshold.
  263                          */
  264                         if (last_evtp != NULL && !last_printed)
  265                                 BTC_DELTA_PRINT(last_evtp, last_msecs,
  266                                     last_dmsecs);
  267                         BTC_DELTA_PRINT(evtp, msecs, dmsecs);
  268                         printed = true;
  269                 } else if (dthres == 0) {
  270                         BTC_DELTA_PRINT(evtp, msecs, dmsecs);
  271                         printed = true;
  272                 }
  273                 if (first_msecs == 0 || msecs < first_msecs)
  274                         first_msecs = msecs;
  275                 last_evtp = evtp;
  276                 last_msecs = msecs;
  277                 last_dmsecs = dmsecs;
  278                 last_printed = printed;
  279                 maybe_yield();
  280 next:
  281                 i = (i + 1) % btp->size;
  282         } while (i != curr);
  283 
  284         total_dmsecs = last_msecs > first_msecs ?
  285             (last_msecs - first_msecs) : 0;
  286         if (sbp != NULL)
  287                 sbuf_printf(sbp, "Total measured time: %ju msecs\n",
  288                     (uintmax_t)total_dmsecs);
  289         else
  290                 printf("Total measured time: %ju msecs\n",
  291                     (uintmax_t)total_dmsecs);
  292 }
  293 
  294 /*
  295  * Dump trace table entries to the console, given a delta threshold.
  296  */
  297 void
  298 boottrace_dump_console(void)
  299 {
  300         if (!boottrace_enabled)
  301                 return;
  302 
  303         if (shutdown || rebooting || KERNEL_PANICKED()) {
  304                 boottrace_display(NULL, &st, shutdown_trace_threshold);
  305         } else {
  306                 boottrace_display(NULL, &bt, 0);
  307                 boottrace_display(NULL, &rt, 0);
  308         }
  309 }
  310 
  311 /*
  312  * Records a new tracing event to the specified table.
  313  *
  314  * We don't use a lock because we want this to be callable from interrupt
  315  * context.
  316  */
  317 static int
  318 dotrace(struct bt_table *btp, const char *eventname, const char *tdname)
  319 {
  320         uint32_t idx, nxt;
  321         struct rusage usage;
  322 
  323         MPASS(boottrace_enabled);
  324         if (tdname == NULL)
  325                 tdname = (curproc->p_flag & P_SYSTEM) ?
  326                     curthread->td_name : curproc->p_comm;
  327 
  328         dprintf("dotrace[");
  329         dprintf("cpu=%u, pid=%d, tsc=%ju, tick=%d, td='%s', event='%s'",
  330             PCPU_GET(cpuid), curthread->td_proc->p_pid,
  331             (uintmax_t)get_cyclecount(), ticks, tdname, eventname);
  332         if (btp->table == NULL) {
  333                 btp->drops_early++;
  334                 dprintf(", return=ENOSPC_1]\n");
  335                 return (ENOSPC);
  336         }
  337 
  338         /* Claim a slot in the table. */
  339         do {
  340                 idx = btp->curr;
  341                 nxt = (idx + 1) % btp->size;
  342                 if (nxt == 0 && btp->wrap == 0) {
  343                         btp->drops_full++;
  344                         dprintf(", return=ENOSPC_2]\n");
  345                         return (ENOSPC);
  346                 }
  347         } while (!atomic_cmpset_int(&btp->curr, idx, nxt));
  348 
  349         btp->table[idx].cpuid = PCPU_GET(cpuid);
  350         btp->table[idx].tsc = get_cyclecount(),
  351         btp->table[idx].tick = cpu_ticks();
  352         btp->table[idx].pid = curthread->td_proc->p_pid;
  353 
  354         /*
  355          * Get the resource usage for the process. Don't attempt this for the
  356          * kernel proc0 or for critical section activities.
  357          */
  358         if ((curthread->td_proc == &proc0) || (curthread->td_critnest != 0)) {
  359                 btp->table[idx].cputime = 0;
  360                 btp->table[idx].inblock = 0;
  361                 btp->table[idx].oublock = 0;
  362         } else {
  363                 kern_getrusage(curthread, RUSAGE_CHILDREN, &usage);
  364                 btp->table[idx].cputime =
  365                     (uint64_t)(usage.ru_utime.tv_sec * 1000000 +
  366                     usage.ru_utime.tv_usec + usage.ru_stime.tv_sec * 1000000 +
  367                     usage.ru_stime.tv_usec);
  368                 btp->table[idx].inblock = (uint32_t)usage.ru_inblock;
  369                 btp->table[idx].oublock = (uint32_t)usage.ru_oublock;
  370         }
  371         strlcpy(btp->table[idx].name, eventname, BT_EVENT_NAMELEN);
  372         strlcpy(btp->table[idx].tdname, tdname, BT_EVENT_TDNAMELEN);
  373 
  374         dprintf(", return=0]\n");
  375         return (0);
  376 }
  377 
  378 /*
  379  * Log various boot-time events, with the trace message encoded using
  380  * printf-like arguments.
  381  */
  382 int
  383 boottrace(const char *tdname, const char *fmt, ...)
  384 {
  385         char eventname[BT_EVENT_NAMELEN];
  386         struct bt_table *btp;
  387         va_list ap;
  388 
  389         if (!dotrace_kernel)
  390                  return (ENXIO);
  391 
  392         va_start(ap, fmt);
  393         vsnprintf(eventname, sizeof(eventname), fmt, ap);
  394         va_end(ap);
  395 
  396         btp = &bt;
  397         if (bootdone)
  398                 btp = &rt;
  399         if (shutdown || rebooting || KERNEL_PANICKED())
  400                 btp = &st;
  401 
  402         return (dotrace(btp, eventname, tdname));
  403 }
  404 
  405 /*
  406  * Log a run-time event & switch over to run-time tracing mode.
  407  */
  408 static int
  409 runtrace(const char *eventname, const char *tdname)
  410 {
  411 
  412         bootdone = true;
  413         return (dotrace(&rt, eventname, tdname));
  414 }
  415 
  416 /*
  417  * Parse a boottrace message from userspace.
  418  *
  419  * The input from may contain a ':' to denote tdname. If not, tdname is
  420  * inferred from the process' name.
  421  *
  422  * e.g. reboot(8):SIGINT to init(8)
  423  */
  424 static void
  425 boottrace_parse_message(char *message, char **eventname, char **tdname)
  426 {
  427         char *delim;
  428 
  429         delim = strchr(message, ':');
  430         if (delim != NULL) {
  431                 *delim = '\0';
  432                 *tdname = message;
  433                 *eventname = ++delim;
  434         } else {
  435                 *tdname = curproc->p_comm;
  436                 *eventname = message;
  437         }
  438 }
  439 
  440 static int
  441 _boottrace_sysctl(struct bt_table *btp, struct sysctl_oid *oidp,
  442     struct sysctl_req *req)
  443 {
  444         char message[BT_MSGLEN];
  445         char *eventname, *tdname;
  446         int error;
  447 
  448         if (!dotrace_user)
  449                return (ENXIO);
  450 
  451         message[0] = '\0';
  452         error = sysctl_handle_string(oidp, message, sizeof(message), req);
  453         if (error)
  454                 return (error);
  455 
  456         boottrace_parse_message(message, &eventname, &tdname);
  457         error = dotrace(btp, eventname, tdname);
  458         if (error == ENOSPC) {
  459                 /* Ignore table full error. */
  460                 error = 0;
  461         }
  462         return (error);
  463 }
  464 
  465 static int
  466 sysctl_log(SYSCTL_HANDLER_ARGS)
  467 {
  468         struct sbuf *sbuf;
  469         int error;
  470 
  471         if (!boottrace_enabled || req->newptr != NULL)
  472                 return (0);
  473 
  474         sbuf = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
  475         boottrace_display(sbuf, &bt, 0);
  476         boottrace_display(sbuf, &rt, 0);
  477         sbuf_finish(sbuf);
  478         error = SYSCTL_OUT(req, sbuf_data(sbuf), sbuf_len(sbuf));
  479         sbuf_delete(sbuf);
  480 
  481         return (error);
  482 }
  483 
  484 static int
  485 sysctl_boottrace(SYSCTL_HANDLER_ARGS)
  486 {
  487 
  488         if (!boottrace_enabled)
  489                 return (0);
  490 
  491         /* No output */
  492         if (req->newptr == NULL)
  493                 return (0);
  494 
  495         /* Trace to rt if we have reached multi-user. */
  496         return (_boottrace_sysctl(bootdone ? &rt : &bt, oidp, req));
  497 }
  498 
  499 /*
  500  * Log a run-time event and switch over to run-time tracing mode.
  501  */
  502 static int
  503 sysctl_runtrace(SYSCTL_HANDLER_ARGS)
  504 {
  505 
  506         if (!boottrace_enabled)
  507                 return (0);
  508 
  509         /* No output */
  510         if (req->newptr == NULL)
  511                 return (0);
  512 
  513         bootdone = true;
  514         return (_boottrace_sysctl(&rt, oidp, req));
  515 }
  516 
  517 /*
  518  * Log a shutdown-time event and switch over to shutdown tracing mode.
  519  */
  520 static int
  521 sysctl_shuttrace(SYSCTL_HANDLER_ARGS)
  522 {
  523 
  524         if (!boottrace_enabled)
  525                 return (0);
  526 
  527         /* No output */
  528         if (req->newptr == NULL)
  529                 return (0);
  530 
  531         shutdown = true;
  532         return (_boottrace_sysctl(&st, oidp, req));
  533 }
  534 
  535 /*
  536  * Reset the runtime tracing buffer.
  537  */
  538 void
  539 boottrace_reset(const char *actor)
  540 {
  541         char tmpbuf[64];
  542 
  543         snprintf(tmpbuf, sizeof(tmpbuf), "reset: %s", actor);
  544         runtrace(tmpbuf, NULL);
  545 }
  546 
  547 /*
  548  * Note that a resize implies a reset, i.e., the index is reset to 0.
  549  * We never shrink the array; we can only increase its size.
  550  */
  551 int
  552 boottrace_resize(u_int newsize)
  553 {
  554 
  555         if (newsize <= rt.size) {
  556                 return (EINVAL);
  557         }
  558         rt.table = realloc(rt.table, newsize * sizeof(struct bt_event),
  559             M_BOOTTRACE, M_WAITOK | M_ZERO);
  560         if (rt.table == NULL)
  561                 return (ENOMEM);
  562 
  563         rt.size = newsize;
  564         boottrace_reset("boottrace_resize");
  565         return (0);
  566 }
  567 
  568 static int
  569 sysctl_boottrace_reset(SYSCTL_HANDLER_ARGS)
  570 {
  571 
  572         if (!boottrace_enabled)
  573                 return (0);
  574 
  575         if (req->newptr != NULL)
  576                 boottrace_reset("sysctl_boottrace_reset");
  577 
  578         return (0);
  579 }
  580 
  581 static void
  582 boottrace_init(void)
  583 {
  584 
  585         if (!boottrace_enabled)
  586                 return;
  587 
  588         /* Boottime trace table */
  589         bt.size = BT_TABLE_DEFSIZE;
  590         TUNABLE_INT_FETCH("kern.boottrace.table_size", &bt.size);
  591         bt.size = max(bt.size, BT_TABLE_MINSIZE);
  592         bt.table = malloc(bt.size * sizeof(struct bt_event), M_BOOTTRACE,
  593             M_WAITOK | M_ZERO);
  594 
  595         /* Stick in an initial entry. */
  596         bt.table[0].cpuid = PCPU_GET(cpuid);
  597         strlcpy(bt.table[0].tdname, "boottime", BT_EVENT_TDNAMELEN);
  598         strlcpy(bt.table[0].name, "initial event", BT_EVENT_NAMELEN);
  599         bt.curr = 1;
  600 
  601         /* Run-time trace table (may wrap-around). */
  602         rt.wrap = 1;
  603         rt.size = BT_TABLE_RUNSIZE;
  604         rt.table = malloc(rt.size * sizeof(struct bt_event), M_BOOTTRACE,
  605             M_WAITOK | M_ZERO);
  606 
  607         /* Shutdown trace table */
  608         st.size = BT_TABLE_SHTSIZE;
  609         st.table = malloc(st.size * sizeof(struct bt_event), M_BOOTTRACE,
  610             M_WAITOK | M_ZERO);
  611 }
  612 SYSINIT(boottrace, SI_SUB_CPU, SI_ORDER_ANY, boottrace_init, 0);

Cache object: 3099cb96c327145f1cf47e55642cd908


[ 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.