[DTrace-devel] [PATCH v2] sdt: consolidate the SDT infrastructure in its own provider framework

Kris Van Hees kris.van.hees at oracle.com
Thu May 18 19:30:35 UTC 2023


The various SDT providers are implemented using the same underlying
mechanisms.  A common SDT infrastructure avoids code duplication.

Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/Build             |   1 +
 libdtrace/dt_provider_sdt.c | 165 ++++++++++++++++++++++++++++++++++++
 libdtrace/dt_provider_sdt.h |  61 +++++++++++++
 3 files changed, 227 insertions(+)
 create mode 100644 libdtrace/dt_provider_sdt.c
 create mode 100644 libdtrace/dt_provider_sdt.h

diff --git a/libdtrace/Build b/libdtrace/Build
index 299cb128..89972c66 100644
--- a/libdtrace/Build
+++ b/libdtrace/Build
@@ -57,6 +57,7 @@ libdtrace-build_SOURCES = dt_aggregate.c \
 			  dt_prov_syscall.c \
 			  dt_prov_uprobe.c \
 			  dt_provider.c \
+			  dt_provider_sdt.c \
 			  dt_provider_tp.c \
 			  dt_regset.c \
 			  dt_string.c \
diff --git a/libdtrace/dt_provider_sdt.c b/libdtrace/dt_provider_sdt.c
new file mode 100644
index 00000000..ebd8b107
--- /dev/null
+++ b/libdtrace/dt_provider_sdt.c
@@ -0,0 +1,165 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ *
+ * Provider support code for tracepoint-based probes.
+ */
+#include <errno.h>
+#include <ctype.h>
+
+#include "dt_provider_sdt.h"
+#include "dt_probe.h"
+#include "dt_impl.h"
+
+typedef struct sdt_data {
+	const probe_dep_t	*probes;
+	const probe_arg_t	*probe_args;
+} sdt_data_t;
+
+/*
+ * Create an SDT provider and populate it from the provided list of probes
+ * (with dependency information) and probe argument data.
+ */
+int
+dt_sdt_populate(dtrace_hdl_t *dtp, const char *prvname, const char *modname,
+		const dt_provimpl_t *ops, const dtrace_pattr_t *pattr,
+		const probe_arg_t *probe_args, const probe_dep_t *probes)
+{
+	dt_provider_t		*prv;
+	const probe_arg_t	*arg;
+	sdt_data_t		*sdp;
+	int			n = 0;
+
+	sdp = dt_alloc(dtp, sizeof(sdt_data_t));
+	if (sdp == NULL)
+		return 0;
+
+	sdp->probes = probes;
+	sdp->probe_args = probe_args;
+	prv = dt_provider_create(dtp, prvname, ops, pattr, sdp);
+	if (prv == NULL)
+		return 0;
+
+	/*
+	 * Create SDT probes based on the probe_args list.  Since each probe
+	 * will have at least one entry (with argno == 0), we can use those
+	 * entries to identify the probe names.
+	 */
+	for (arg = &probe_args[0]; arg->name != NULL; arg++) {
+		if (arg->argno == 0 &&
+		    dt_probe_insert(dtp, prv, prvname, modname, "", arg->name,
+				    NULL))
+			n++;
+	}
+
+	return n;
+}
+
+/*
+ * Add an SDT probe as a dependent probe for an underlying probe that has been
+ * provided by another provider.
+ */
+static int
+add_dependency(dtrace_hdl_t *dtp, dt_probe_t *uprp, void *arg)
+{
+	dt_probe_t	*prp = arg;
+
+	dt_probe_add_dependent(dtp, uprp, prp);
+	dt_probe_enable(dtp, uprp);
+
+	return 0;
+}
+
+/*
+ * Enable an SDT probe.
+ */
+void
+dt_sdt_enable(dtrace_hdl_t *dtp, dt_probe_t *prp)
+{
+	const probe_dep_t	*dep;
+
+	for (dep = ((sdt_data_t *)prp->prov->prv_data)->probes;
+	     dep->name != NULL; dep++) {
+		dtrace_probedesc_t	pd;
+
+		if (strcmp(prp->desc->prb, dep->name) != 0)
+			continue;
+
+		if (dtrace_str2desc(dtp, dep->spec, dep->str, &pd) == -1)
+			return;
+
+		dt_probe_iter(dtp, &pd, add_dependency, NULL, prp);
+
+		free((void *)pd.prv);
+		free((void *)pd.mod);
+		free((void *)pd.fun);
+		free((void *)pd.prb);
+	}
+
+	/*
+	 * Finally, ensure we're in the list of enablings as well.
+	 * (This ensures that, among other things, the probes map
+	 * gains entries for us.)
+	 */
+	if (!dt_in_list(&dtp->dt_enablings, prp))
+		dt_list_append(&dtp->dt_enablings, prp);
+}
+
+/*
+ * Populate the probe arguments for the given probe.
+ */
+int
+dt_sdt_probe_info(dtrace_hdl_t *dtp, const dt_probe_t *prp, int *argcp,
+		  dt_argdesc_t **argvp)
+{
+	int			i;
+	int			pidx = -1;
+	int			argc = 0;
+	dt_argdesc_t		*argv = NULL;
+	const probe_arg_t	*probe_args =
+				((sdt_data_t *)prp->prov->prv_data)->probe_args;
+	const probe_arg_t	*arg;
+
+	for (arg = &probe_args[i = 0]; arg->name != NULL; arg++, i++) {
+		if (strcmp(arg->name, prp->desc->prb) == 0) {
+			if (pidx == -1) {
+				pidx = i;
+
+				if (arg->argdesc.native == NULL)
+					break;
+			}
+
+			argc++;
+		}
+	}
+
+	if (argc == 0)
+		goto done;
+
+	argv = dt_zalloc(dtp, argc * sizeof(dt_argdesc_t));
+	if (!argv)
+		return -ENOMEM;
+
+	for (i = pidx; i < pidx + argc; i++) {
+		const probe_arg_t	*arg = &probe_args[i];
+
+		argv[arg->argno] = arg->argdesc;
+	}
+
+done:
+	*argcp = argc;
+	*argvp = argv;
+
+	return 0;
+}
+
+/*
+ * Clean up SDT-specific data.
+ */
+void
+dt_sdt_destroy(dtrace_hdl_t *dtp, void *datap)
+{
+	dt_free(dtp, datap);
+}
diff --git a/libdtrace/dt_provider_sdt.h b/libdtrace/dt_provider_sdt.h
new file mode 100644
index 00000000..86f3b84b
--- /dev/null
+++ b/libdtrace/dt_provider_sdt.h
@@ -0,0 +1,61 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+#ifndef	_DT_PROVIDER_SDT_H
+#define	_DT_PROVIDER_SDT_H
+
+#include <sys/dtrace_types.h>
+#include <dt_provider.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * Probe dependencies
+ *
+ * SDT probes are implemented using probes made available by other providers.
+ * THe probe dependency table associates each SDT probe with one or more probe
+ * specifications (possibly containing wildcards).  Each matching probe will
+ * have SDT lockstat probe added as a dependent probe.
+ */
+typedef struct probe_dep {
+	const char		*name;			/* probe name */
+	dtrace_probespec_t	spec;			/* spec type */
+	const char		*str;			/* spec string */
+} probe_dep_t;
+
+/*
+ * Probe signature specifications
+ *
+ * This table *must* group the arguments of probes.  I.e. the arguments of a
+ * given probe must be listed in consecutive records.
+ *
+ * A single probe entry that mentions only name of the probe indicates a probe
+ * that provides no arguments.
+ */
+typedef struct probe_arg {
+	const char	*name;			/* name of probe */
+	int		argno;			/* argument number */
+	dt_argdesc_t	argdesc;		/* argument description */
+} probe_arg_t;
+
+extern int dt_sdt_populate(dtrace_hdl_t *dtp, const char *prvname,
+			   const char *modname, const dt_provimpl_t *ops,
+			   const dtrace_pattr_t *pattr,
+			   const probe_arg_t *probe_args,
+			   const probe_dep_t *probes);
+extern void dt_sdt_enable(dtrace_hdl_t *dtp, struct dt_probe *prp);
+extern int dt_sdt_probe_info(dtrace_hdl_t *dtp, const struct dt_probe *prp,
+			     int *argcp, dt_argdesc_t **argvp);
+extern void dt_sdt_destroy(dtrace_hdl_t *dtp, void *datap);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _DT_PROVIDER_SDT_H */
-- 
2.40.1




More information about the DTrace-devel mailing list