Module Name: src Committed By: christos Date: Fri Oct 2 17:13:32 UTC 2015
Modified Files: src/external/cddl/osnet/dev/sdt: sdt.c Log Message: Merge conflicts To generate a diff of this commit: cvs rdiff -u -r1.13 -r1.14 src/external/cddl/osnet/dev/sdt/sdt.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/external/cddl/osnet/dev/sdt/sdt.c diff -u src/external/cddl/osnet/dev/sdt/sdt.c:1.13 src/external/cddl/osnet/dev/sdt/sdt.c:1.14 --- src/external/cddl/osnet/dev/sdt/sdt.c:1.13 Fri Oct 2 12:59:23 2015 +++ src/external/cddl/osnet/dev/sdt/sdt.c Fri Oct 2 13:13:32 2015 @@ -38,23 +38,33 @@ * responsible for destroying individual probes when a kernel module is * unloaded; in particular, probes may not span multiple kernel modules. */ +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: sdt.c,v 1.14 2015/10/02 17:13:32 christos Exp $"); #include <sys/cdefs.h> #include <sys/param.h> #include <sys/systm.h> #include <sys/conf.h> +#ifdef __FreeBSD__ #include <sys/eventhandler.h> +#endif #include <sys/kernel.h> #include <sys/limits.h> +#ifdef __FreeBSD__ #include <sys/linker.h> #include <sys/linker_set.h> +#endif #include <sys/lock.h> +#ifdef __FreeBSD__ #include <sys/lockstat.h> +#endif #include <sys/malloc.h> +#include <sys/kmem.h> #include <sys/module.h> #include <sys/mutex.h> #include <sys/queue.h> +#define KDTRACE_HOOKS #include <sys/sdt.h> #include <sys/dtrace.h> @@ -62,19 +72,23 @@ /* DTrace methods. */ static void sdt_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *); -static void sdt_provide_probes(void *, dtrace_probedesc_t *); +static void sdt_provide_probes(void *, const dtrace_probedesc_t *); static void sdt_destroy(void *, dtrace_id_t, void *); -static void sdt_enable(void *, dtrace_id_t, void *); +static int sdt_enable(void *, dtrace_id_t, void *); static void sdt_disable(void *, dtrace_id_t, void *); static void sdt_load(void); static int sdt_unload(void); static void sdt_create_provider(struct sdt_provider *); static void sdt_create_probe(struct sdt_probe *); +#ifdef __FreeBSD__ static void sdt_kld_load(void *, struct linker_file *); static void sdt_kld_unload_try(void *, struct linker_file *, int *); +#endif -static MALLOC_DEFINE(M_SDT, "SDT", "DTrace SDT providers"); +MALLOC_DECLARE(M_SDT); +MALLOC_DEFINE(M_SDT, "SDT", "DTrace SDT providers"); +#define SDT_KASSERT(cond, msg) KASSERT(cond) static dtrace_pattr_t sdt_attr = { { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON }, @@ -97,10 +111,37 @@ static dtrace_pops_t sdt_pops = { sdt_destroy, }; +#ifdef __NetBSD__ +static int +sdt_open(dev_t dev, int flags, int mode, struct lwp *l) +{ + return (0); +} + +static const struct cdevsw sdt_cdevsw = { + sdt_open, noclose, noread, nowrite, noioctl, + nostop, notty, nopoll, nommap, nokqfilter, nodiscard, + D_OTHER +}; +#endif + static TAILQ_HEAD(, sdt_provider) sdt_prov_list; +#ifdef __FreeBSD__ eventhandler_tag sdt_kld_load_tag; eventhandler_tag sdt_kld_unload_try_tag; +#endif + +#ifdef __NetBSD__ +static char * +strdup(const char *s, const struct malloc_type *m) +{ + size_t l = strlen(s) + 1; + char *d = malloc(l, m, M_WAITOK); + memcpy(d, s, l); + return d; +} +#endif static void sdt_create_provider(struct sdt_provider *prov) @@ -145,14 +186,16 @@ sdt_create_probe(struct sdt_probe *probe if (strcmp(prov->name, probe->prov->name) == 0) break; - KASSERT(prov != NULL, ("probe defined without a provider")); + SDT_KASSERT(prov != NULL, ("probe defined without a provider")); +#ifdef __FreeBSD__ /* If no module name was specified, use the module filename. */ if (*probe->mod == 0) { len = strlcpy(mod, probe->sdtp_lf->filename, sizeof(mod)); if (len > 3 && strcmp(mod + len - 3, ".ko") == 0) mod[len - 3] = '\0'; } else +#endif strlcpy(mod, probe->mod, sizeof(mod)); /* @@ -187,19 +230,26 @@ sdt_create_probe(struct sdt_probe *probe * requires one of provide_probes and provide_module to be defined. */ static void -sdt_provide_probes(void *arg, dtrace_probedesc_t *desc) +sdt_provide_probes(void *arg, const dtrace_probedesc_t *desc) { } -static void +static int sdt_enable(void *arg __unused, dtrace_id_t id, void *parg) { struct sdt_probe *probe = parg; +#ifdef SDT_DEBUG + printf("sdt: %s\n", __func__); +#endif + probe->id = id; +#ifdef __FreeBSD__ probe->sdtp_lf->nenabled++; if (strcmp(probe->prov->name, "lockstat") == 0) lockstat_enabled++; +#endif + return 1; } static void @@ -207,12 +257,18 @@ sdt_disable(void *arg __unused, dtrace_i { struct sdt_probe *probe = parg; - KASSERT(probe->sdtp_lf->nenabled > 0, ("no probes enabled")); + SDT_KASSERT(probe->sdtp_lf->nenabled > 0, ("no probes enabled")); + +#ifdef SDT_DEBUG + printf("sdt: %s\n", __func__); +#endif +#ifdef __FreeBSD__ if (strcmp(probe->prov->name, "lockstat") == 0) lockstat_enabled--; - probe->id = 0; probe->sdtp_lf->nenabled--; +#endif + probe->id = 0; } static void @@ -221,6 +277,16 @@ sdt_getargdesc(void *arg, dtrace_id_t id struct sdt_argtype *argtype; struct sdt_probe *probe = parg; +#ifdef SDT_DEBUG + printf("sdt: %s probe %d\n", __func__, id); + printf("%s: probe %d (%s:%s:%s:%s).%d\n", + __func__, id, + probe->provider, + probe->module, + probe->function, + probe->name, + desc->dtargd_ndx); +#endif if (desc->dtargd_ndx >= probe->n_args) { desc->dtargd_ndx = DTRACE_ARGNONE; return; @@ -248,6 +314,7 @@ sdt_destroy(void *arg, dtrace_id_t id, v { } +#ifdef __FreeBSD__ /* * Called from the kernel linker when a module is loaded, before * dtrace_module_loaded() is called. This is done so that it's possible to @@ -332,47 +399,118 @@ sdt_linker_file_cb(linker_file_t lf, voi return (0); } +#endif +#ifdef __NetBSD__ +/* + * weak symbols don't work in kernel modules; link set end symbols are + * weak by default, so we kill that. + */ +#undef __weak +#define __weak +__link_set_decl(sdt_providers_set, struct std_provider); +__link_set_decl(sdt_probes_set, struct std_probe); +__link_set_decl(sdt_argtypes_set, struct sdt_argtype); + +/* + * Unfortunately we don't have linker set functions and event handlers + * to support loading and unloading probes in modules... Currently if + * modules have probes, if the modules are loaded when sdt is loaded + * they will work, but they will crash unloading. + */ static void -sdt_load() +sdt_link_set_load(void) { + struct sdt_provider * const *provider; + struct sdt_probe **probe; + struct sdt_argtype **argtype; - TAILQ_INIT(&sdt_prov_list); + __link_set_foreach(provider, sdt_providers_set) { + sdt_create_provider(*provider); + } - sdt_probe_func = dtrace_probe; + __link_set_foreach(probe, sdt_probes_set) { + (*probe)->sdtp_lf = NULL; // XXX: we don't support it + sdt_create_probe(*probe); + TAILQ_INIT(&(*probe)->argtype_list); + } - sdt_kld_load_tag = EVENTHANDLER_REGISTER(kld_load, sdt_kld_load, NULL, - EVENTHANDLER_PRI_ANY); - sdt_kld_unload_try_tag = EVENTHANDLER_REGISTER(kld_unload_try, - sdt_kld_unload_try, NULL, EVENTHANDLER_PRI_ANY); + __link_set_foreach(argtype, sdt_argtypes_set) { + (*argtype)->probe->n_args++; + TAILQ_INSERT_TAIL(&(*argtype)->probe->argtype_list, + *argtype, argtype_entry); + } +} +static void +sdt_link_set_unload(void) +{ + struct sdt_provider **curr, *prov, *tmp; + + /* + * Go through all the providers declared in this linker file and + * unregister any that aren't declared in another loaded file. + */ + __link_set_foreach(curr, sdt_providers_set) { + TAILQ_FOREACH_SAFE(prov, &sdt_prov_list, prov_entry, tmp) { + if (strcmp(prov->name, (*curr)->name) != 0) + continue; + + if (prov->sdt_refs == 1) { + if (dtrace_unregister(prov->id) != 0) { + return; + } + TAILQ_REMOVE(&sdt_prov_list, prov, prov_entry); + free(__UNCONST(prov->name), M_SDT); + free(prov, M_SDT); + } else + prov->sdt_refs--; + break; + } + } +} +#endif + + +static void +sdt_load(void) +{ + TAILQ_INIT(&sdt_prov_list); + + sdt_init(dtrace_probe); +#ifdef __FreeBSD__ /* Pick up probes from the kernel and already-loaded linker files. */ linker_file_foreach(sdt_linker_file_cb, NULL); +#endif +#ifdef __NetBSD__ + sdt_link_set_load(); +#endif } static int -sdt_unload() +sdt_unload(void) { struct sdt_provider *prov, *tmp; int ret; - EVENTHANDLER_DEREGISTER(kld_load, sdt_kld_load_tag); - EVENTHANDLER_DEREGISTER(kld_unload_try, sdt_kld_unload_try_tag); - - sdt_probe_func = sdt_probe_stub; + sdt_exit(); +#ifdef __NetBSD__ + sdt_link_set_unload(); +#endif TAILQ_FOREACH_SAFE(prov, &sdt_prov_list, prov_entry, tmp) { ret = dtrace_unregister(prov->id); if (ret != 0) - return (ret); + return ret; TAILQ_REMOVE(&sdt_prov_list, prov, prov_entry); - free(prov->name, M_SDT); + free(__UNCONST(prov->name), M_SDT); free(prov, M_SDT); } - return (0); + return 0; } +#ifdef __FreeBSD__ static int sdt_modevent(module_t mod __unused, int type, void *data __unused) { @@ -402,3 +540,33 @@ DEV_MODULE(sdt, sdt_modevent, NULL); MODULE_VERSION(sdt, 1); MODULE_DEPEND(sdt, dtrace, 1, 1, 1); MODULE_DEPEND(sdt, opensolaris, 1, 1, 1); +#endif + +#ifdef __NetBSD__ +static int +dtrace_sdt_modcmd(modcmd_t cmd, void *data) +{ + int bmajor = -1, cmajor = -1; + int error; + + switch (cmd) { + case MODULE_CMD_INIT: + sdt_load(); + return devsw_attach("sdt", NULL, &bmajor, + &sdt_cdevsw, &cmajor); + case MODULE_CMD_FINI: + error = sdt_unload(); + if (error != 0) + return error; + return devsw_detach(NULL, &sdt_cdevsw); + case MODULE_CMD_AUTOUNLOAD: + return EBUSY; + default: + error = EOPNOTSUPP; + break; + } + return error; +} + +MODULE(MODULE_CLASS_MISC, dtrace_sdt, "dtrace"); +#endif