-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sdt: consolidate the SDT infrastructure in its own provider framework
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@oracle.com> Reviewed-by: Eugene Loh <eugene.loh@oracle.com>
- Loading branch information
Showing
3 changed files
with
227 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 */ |