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_sdt.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 2006-2008 John Birrell <jb@FreeBSD.org>
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer.
    9  * 2. Redistributions in binary form must reproduce the above copyright
   10  *    notice, this list of conditions and the following disclaimer in the
   11  *    documentation and/or other materials provided with the distribution.
   12  * 
   13  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   16  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
   17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   23  * SUCH DAMAGE.
   24  *
   25  * $FreeBSD$
   26  *
   27  * Backend for the Statically Defined Tracing (SDT) kernel support. This is
   28  * required to allow a module to load even though DTrace kernel support may
   29  * not be present. A module may be built with SDT probes in it which are
   30  * registered and deregistered via SYSINIT/SYSUNINIT.
   31  *
   32  */
   33 
   34 #include "opt_kdtrace.h"
   35 
   36 #include <sys/cdefs.h>
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/kernel.h>
   40 #include <sys/linker.h>
   41 #include <sys/lock.h>
   42 #include <sys/proc.h>
   43 #include <sys/sx.h>
   44 #include <sys/sdt.h>
   45 
   46 /*
   47  * This is the list of statically defined tracing providers.
   48  */
   49 static TAILQ_HEAD(sdt_provider_list_head, sdt_provider) sdt_provider_list;
   50 
   51 /*
   52  * Mutex to serialise access to the SDT provider list.
   53  */
   54 static struct sx sdt_sx;
   55 
   56 /*
   57  * Hook for the DTrace probe function. The 'sdt' provider will set this
   58  * to dtrace_probe when it loads.
   59  */
   60 sdt_probe_func_t sdt_probe_func = sdt_probe_stub;
   61 
   62 static sdt_provider_listall_func_t sdt_provider_register_func = NULL;
   63 static sdt_provider_listall_func_t sdt_provider_deregister_func = NULL;
   64 static sdt_probe_listall_func_t sdt_probe_register_func = NULL;
   65 
   66 static void *sdt_provider_register_arg;
   67 static void *sdt_provider_deregister_arg;
   68 static void *sdt_probe_register_arg;
   69 
   70 static int sdt_provider_listall_locked(sdt_provider_listall_func_t, void *);
   71 
   72 /*
   73  * This is a stub for probe calls in case kernel DTrace support isn't
   74  * compiled in. It should never get called because there is no DTrace
   75  * support to enable it.
   76  */
   77 void
   78 sdt_probe_stub(u_int32_t id, uintptr_t arg0, uintptr_t arg1,
   79     uintptr_t arg2, uintptr_t arg3, uintptr_t arg4)
   80 {
   81         printf("sdt_probe_stub: Why did this get called?\n");
   82 }
   83 
   84 /*
   85  * Called from SYSINIT to register a provider.
   86  */
   87 void
   88 sdt_provider_register(void *arg)
   89 {
   90         struct sdt_provider *prov = arg;
   91 
   92         sx_xlock(&sdt_sx);
   93 
   94         TAILQ_INSERT_TAIL(&sdt_provider_list, prov, prov_entry);
   95 
   96         TAILQ_INIT(&prov->probe_list);
   97 
   98         if (sdt_provider_register_func != NULL)
   99                 sdt_provider_register_func(prov, sdt_provider_register_arg);
  100 
  101         sx_xunlock(&sdt_sx);
  102 }
  103 
  104 /*
  105  * Called from SYSUNINIT to de-register a provider.
  106  */
  107 void
  108 sdt_provider_deregister(void *arg)
  109 {
  110         struct sdt_provider *prov = arg;
  111 
  112         sx_xlock(&sdt_sx);
  113 
  114         TAILQ_REMOVE(&sdt_provider_list, prov, prov_entry);
  115 
  116         if (sdt_provider_deregister_func != NULL)
  117                 sdt_provider_deregister_func(prov, sdt_provider_deregister_arg);
  118 
  119         sx_xunlock(&sdt_sx);
  120 }
  121 
  122 /*
  123  * Called from SYSINIT to register a statically defined trace probe.
  124  */
  125 void
  126 sdt_probe_register(void *arg)
  127 {
  128         struct sdt_probe *probe = arg;
  129 
  130         /*
  131          * Check the reference structure version. Only version 1 is
  132          * supported at the moment.
  133          */
  134         if (probe->version != sizeof(struct sdt_probe)) {
  135                 printf("%s:%s:%s has version %d when %d required\n", probe->mod, probe->func, probe->name, probe->version, (int) sizeof(struct sdt_probe));
  136                 return;
  137         }
  138 
  139         sx_xlock(&sdt_sx);
  140 
  141         TAILQ_INSERT_TAIL(&probe->prov->probe_list, probe, probe_entry);
  142 
  143         TAILQ_INIT(&probe->argtype_list);
  144 
  145         probe->state = SDT_INIT;
  146 
  147         if (sdt_probe_register_func != NULL)
  148                 sdt_probe_register_func(probe, sdt_provider_register_arg);
  149 
  150         sx_xunlock(&sdt_sx);
  151 }
  152 
  153 /*
  154  * Called from SYSUNINIT to de-register a statically defined trace probe.
  155  */
  156 void
  157 sdt_probe_deregister(void *arg)
  158 {
  159         struct sdt_probe *probe = arg;
  160 
  161         sx_xlock(&sdt_sx);
  162 
  163         if (probe->state == SDT_INIT) {
  164                 TAILQ_REMOVE(&probe->prov->probe_list, probe, probe_entry);
  165                 probe->state = SDT_UNINIT;
  166         }
  167 
  168         sx_xunlock(&sdt_sx);
  169 }
  170 
  171 /*
  172  * Called from SYSINIT to register a statically defined trace probe argument.
  173  */
  174 void
  175 sdt_argtype_register(void *arg)
  176 {
  177         struct sdt_argtype *argtype = arg;
  178 
  179         sx_xlock(&sdt_sx);
  180 
  181         TAILQ_INSERT_TAIL(&argtype->probe->argtype_list, argtype, argtype_entry);
  182 
  183         argtype->probe->n_args++;
  184 
  185         sx_xunlock(&sdt_sx);
  186 }
  187 
  188 /*
  189  * Called from SYSUNINIT to de-register a statically defined trace probe argument.
  190  */
  191 void
  192 sdt_argtype_deregister(void *arg)
  193 {
  194         struct sdt_argtype *argtype = arg;
  195 
  196         sx_xlock(&sdt_sx);
  197 
  198         TAILQ_REMOVE(&argtype->probe->argtype_list, argtype, argtype_entry);
  199 
  200         sx_xunlock(&sdt_sx);
  201 }
  202 
  203 static void
  204 sdt_init(void *arg)
  205 { 
  206         sx_init_flags(&sdt_sx, "Statically Defined Tracing", SX_NOWITNESS);
  207 
  208         TAILQ_INIT(&sdt_provider_list);
  209 }
  210 
  211 SYSINIT(sdt, SI_SUB_KDTRACE, SI_ORDER_FIRST, sdt_init, NULL);
  212 
  213 static void
  214 sdt_uninit(void *arg)
  215 { 
  216         sx_destroy(&sdt_sx);
  217 }
  218 
  219 SYSUNINIT(sdt, SI_SUB_KDTRACE, SI_ORDER_FIRST, sdt_uninit, NULL);
  220 
  221 /*
  222  * List statically defined tracing providers.
  223  */
  224 int
  225 sdt_provider_listall(sdt_provider_listall_func_t callback_func, void *arg)
  226 {
  227         int error;
  228 
  229         sx_xlock(&sdt_sx);
  230         error = sdt_provider_listall_locked(callback_func, arg);
  231         sx_xunlock(&sdt_sx);
  232 
  233         return (error);
  234 }
  235 
  236 static int
  237 sdt_provider_listall_locked(sdt_provider_listall_func_t callback_func,
  238     void *arg)
  239 {
  240         int error = 0;
  241         struct sdt_provider *prov;
  242 
  243         sx_assert(&sdt_sx, SX_XLOCKED);
  244 
  245         TAILQ_FOREACH(prov, &sdt_provider_list, prov_entry) {
  246                 if ((error = callback_func(prov, arg)) != 0)
  247                         break;
  248         }
  249 
  250         return (error);
  251 }
  252 
  253 /*
  254  * List statically defined tracing probes.
  255  */
  256 int
  257 sdt_probe_listall(struct sdt_provider *prov, 
  258     sdt_probe_listall_func_t callback_func,void *arg)
  259 {
  260         int error = 0;
  261         int locked;
  262         struct sdt_probe *probe;
  263 
  264         locked = sx_xlocked(&sdt_sx);
  265         if (!locked)
  266                 sx_xlock(&sdt_sx);
  267 
  268         TAILQ_FOREACH(probe, &prov->probe_list, probe_entry) {
  269                 if ((error = callback_func(probe, arg)) != 0)
  270                         break;
  271         }
  272 
  273         if (!locked)
  274                 sx_xunlock(&sdt_sx);
  275 
  276         return (error);
  277 }
  278 
  279 /*
  280  * List statically defined tracing probe arguments.
  281  */
  282 int
  283 sdt_argtype_listall(struct sdt_probe *probe, 
  284     sdt_argtype_listall_func_t callback_func,void *arg)
  285 {
  286         int error = 0;
  287         int locked;
  288         struct sdt_argtype *argtype;
  289 
  290         locked = sx_xlocked(&sdt_sx);
  291         if (!locked)
  292                 sx_xlock(&sdt_sx);
  293 
  294         TAILQ_FOREACH(argtype, &probe->argtype_list, argtype_entry) {
  295                 if ((error = callback_func(argtype, arg)) != 0)
  296                         break;
  297         }
  298 
  299         if (!locked)
  300                 sx_xunlock(&sdt_sx);
  301 
  302         return (error);
  303 }
  304 
  305 void sdt_register_callbacks(sdt_provider_listall_func_t register_prov, 
  306     void *reg_prov_arg, sdt_provider_listall_func_t deregister_prov, 
  307     void *dereg_prov_arg, sdt_probe_listall_func_t register_probe, 
  308     void * reg_probe_arg)
  309 {
  310 
  311         sx_xlock(&sdt_sx);
  312         sdt_provider_register_func = register_prov;
  313         sdt_provider_deregister_func = deregister_prov;
  314         sdt_probe_register_func = register_probe;
  315 
  316         sdt_provider_register_arg = reg_prov_arg;
  317         sdt_provider_deregister_arg = dereg_prov_arg;
  318         sdt_probe_register_arg = reg_probe_arg;
  319 
  320         sdt_provider_listall_locked(register_prov, reg_prov_arg);
  321         sx_xunlock(&sdt_sx);
  322 }
  323 
  324 void sdt_deregister_callbacks(void)
  325 {
  326 
  327         sx_xlock(&sdt_sx);
  328         sdt_provider_listall_locked(sdt_provider_deregister_func, 
  329             sdt_provider_deregister_arg);
  330 
  331         sdt_provider_register_func = NULL;
  332         sdt_provider_deregister_func = NULL;
  333         sdt_probe_register_func = NULL;
  334 
  335         sdt_provider_register_arg = NULL;
  336         sdt_provider_deregister_arg = NULL;
  337         sdt_probe_register_arg = NULL;
  338         sx_xunlock(&sdt_sx);
  339 }

Cache object: 32918b6a7a1866b235d5b9b8d014c420


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