From: Alan Maguire <alan.maguire@oracle.com>
To: dtrace@lists.linux.dev
Cc: dtrace-devel@oss.oracle.com, Alan Maguire <alan.maguire@oracle.com>
Subject: [PATCH v4 2/9] libdtrace: share vmlinux BTF/CTF globally to support faster startup
Date: Wed, 12 Aug 2026 14:22:03 +0100 [thread overview]
Message-ID: <20260812132212.527871-3-alan.maguire@oracle.com> (raw)
In-Reply-To: <20260812132212.527871-1-alan.maguire@oracle.com>
In a multiple DTrace session per process environment, it makes sense
to avoid doing expensive operations like reading in vmlinux BTF and
converting it to CTF more than once. Shared (vmlinux) BTF and CTF
generated from it are shared and reference-counted globally here
to cut down on cost. With this change, we can launch ~1 DTrace
session per second.
Note that we need to handle case where -xbtfpath/DTRACE_OPT_BTFPATH
are used as non-default BTF paths; in such cases global shared
BTF is not used in the handle.
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
libdtrace/dt_btf.c | 79 +++++++++++++++++++++++++++++++++++++++++++--
libdtrace/dt_btf.h | 1 +
libdtrace/dt_impl.h | 4 +--
libdtrace/dt_open.c | 5 +--
4 files changed, 81 insertions(+), 8 deletions(-)
diff --git a/libdtrace/dt_btf.c b/libdtrace/dt_btf.c
index 1f793397..7ec824be 100644
--- a/libdtrace/dt_btf.c
+++ b/libdtrace/dt_btf.c
@@ -693,6 +693,9 @@ dt_btf_to_ctf(dtrace_hdl_t *dtp, dt_module_t *dmp, dt_btf_t *btf)
ctf_dict_t *ctf;
ctf_encoding_t enc = { CTF_INT_SIGNED, 0, 0 };
+ if (dmp == NULL && dtp->dt_shared_ctf)
+ return dtp->dt_shared_ctf;
+
ctf = ctf_create(&dtp->dt_ctferr);
if (ctf == NULL)
return NULL;
@@ -764,6 +767,68 @@ out:
}
#endif
+static dt_btf_t *dt_shared_btf = NULL;
+#ifdef HAVE_LIBCTF
+static ctf_dict_t *dt_shared_ctf = NULL;
+#endif
+static pthread_mutex_t dt_shared_mutex = PTHREAD_MUTEX_INITIALIZER;
+static int dt_shared_refcnt = 0;
+
+static int
+dt_shared_get(dtrace_hdl_t *dtp, dt_module_t *dmp)
+{
+ pthread_mutex_lock(&dt_shared_mutex);
+ if (!dt_shared_btf)
+ dt_shared_btf = dt_btf_load_file(dtp, "/sys/kernel/btf/vmlinux");
+ if (dt_shared_btf) {
+ dt_shared_refcnt++;
+ dtp->dt_shared_btf = dmp->dm_btf = dt_shared_btf;
+#ifdef HAVE_LIBCTF
+ if (!dt_shared_ctf) {
+ ctf_dict_t *ctf = dt_btf_to_ctf(dtp, NULL, dt_shared_btf);
+
+ if (ctf)
+ dtp->dt_shared_ctf = dt_shared_ctf = dmp->dm_ctfp = ctf;
+ } else {
+ dtp->dt_shared_ctf = dmp->dm_ctfp = dt_shared_ctf;
+ }
+#endif
+ }
+ pthread_mutex_unlock(&dt_shared_mutex);
+ if (!dt_shared_btf)
+ return -1;
+ return 0;
+}
+
+void
+dt_shared_put(dtrace_hdl_t *dtp)
+{
+ int shared;
+
+ pthread_mutex_lock(&dt_shared_mutex);
+ shared = dtp->dt_shared_btf && dtp->dt_shared_btf == dt_shared_btf;
+ if (shared && --dt_shared_refcnt != 0)
+ goto out;
+
+ dt_btf_destroy(dtp, dtp->dt_shared_btf);
+ dtp->dt_shared_btf = NULL;
+ if (shared)
+ dt_shared_btf = NULL;
+
+#ifdef HAVE_LIBCTF
+ if (shared) {
+ ctf_close(dt_shared_ctf);
+ dt_shared_ctf = NULL;
+ } else {
+ ctf_close(dtp->dt_shared_ctf);
+ }
+ dtp->dt_shared_ctf = NULL;
+#endif
+
+out:
+ pthread_mutex_unlock(&dt_shared_mutex);
+}
+
dt_btf_t *
dt_btf_load_module(dtrace_hdl_t *dtp, dt_module_t *dmp)
{
@@ -774,6 +839,13 @@ dt_btf_load_module(dtrace_hdl_t *dtp, dt_module_t *dmp)
if (dmp->dm_btf)
return dmp->dm_btf;
+ /* Share only the system-default vmlinux BTF. */
+ if (dtp->dt_btf_path == NULL &&
+ strcmp(dmp->dm_name, "vmlinux") == 0) {
+ if (dt_shared_get(dtp, dmp) == 0)
+ return dmp->dm_btf;
+ }
+
/*
* Default: /sys/kernel/btf/<module>
* If "none", disable BTF.
@@ -899,9 +971,12 @@ dt_btf_lookup_name_kind(dtrace_hdl_t *dtp, dt_module_t *dmp, const char *name,
if (strcmp(name, "void") == 0)
return 0;
- /* Ensure the shared BTF is loaded. */
- if (!dtp->dt_shared_btf)
+ /* Ensure the vmlinux BTF base is loaded before considering a module. */
+ if (!dtp->dt_shared_btf) {
dt_btf_load_module(dtp, dtp->dt_exec);
+ if (!dtp->dt_shared_btf)
+ return -ENOENT;
+ }
/* If the module does not have BTF data yet, try to load it. */
if (!btf) {
diff --git a/libdtrace/dt_btf.h b/libdtrace/dt_btf.h
index 2c921a03..b1ed2b65 100644
--- a/libdtrace/dt_btf.h
+++ b/libdtrace/dt_btf.h
@@ -18,6 +18,7 @@ typedef struct dt_btf dt_btf_t;
typedef struct bpf_btf_info btf_info_t;
extern void dt_btf_destroy(dtrace_hdl_t *, dt_btf_t *);
+extern void dt_shared_put(dtrace_hdl_t *);
extern dt_btf_t *dt_btf_load_module(dtrace_hdl_t *, dt_module_t *);
extern ctf_dict_t *dt_btf_module_ctf(dtrace_hdl_t *, dt_module_t *);
extern const char *dt_btf_get_string(dtrace_hdl_t *, const dt_btf_t *,
diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
index 7db2ba93..7ccdc271 100644
--- a/libdtrace/dt_impl.h
+++ b/libdtrace/dt_impl.h
@@ -305,8 +305,8 @@ struct dtrace_hdl {
char *dt_ctfa_path; /* path to vmlinux.ctfa */
ctf_archive_t *dt_ctfa; /* ctf archive for the entire kernel tree */
char *dt_btf_path; /* path to vmlinux.btf */
- struct dt_btf *dt_shared_btf; /* BTF data for the kernel (shared) */
- ctf_file_t *dt_shared_ctf; /* Handle to the shared CTF */
+ struct dt_btf *dt_shared_btf; /* BTF data shared by kernel modules */
+ ctf_file_t *dt_shared_ctf; /* CTF shared by kernel modules */
dt_htab_t *dt_kernpaths; /* hash table of dt_kern_path_t's */
dt_module_t *dt_exec; /* pointer to executable module */
dt_module_t *dt_cdefs; /* pointer to C dynamic type module */
diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c
index 30b8758d..352cec49 100644
--- a/libdtrace/dt_open.c
+++ b/libdtrace/dt_open.c
@@ -1299,10 +1299,7 @@ dtrace_close(dtrace_hdl_t *dtp)
dt_htab_destroy(dtp->dt_mods);
dt_htab_destroy(dtp->dt_kernpaths);
- if (dtp->dt_shared_btf != NULL)
- dt_btf_destroy(dtp, dtp->dt_shared_btf);
- if (dtp->dt_shared_ctf != NULL)
- ctf_close(dtp->dt_shared_ctf);
+ dt_shared_put(dtp);
if (dtp->dt_ctfa != NULL)
ctf_arc_close(dtp->dt_ctfa);
--
2.43.5
next prev parent reply other threads:[~2026-08-12 13:22 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-12 13:22 [PATCH v4 0/9] Add python, PCP support via libdtrace interfaces Alan Maguire
2026-08-12 13:22 ` [PATCH v4 1/9] libdtrace: Support multiple DTrace handles per process Alan Maguire
2026-08-12 13:22 ` Alan Maguire [this message]
2026-08-12 13:22 ` [PATCH v4 3/9] libdtrace: Refactor math functions into dt_math.h Alan Maguire
2026-08-12 13:22 ` [PATCH v4 4/9] python: Add cpython bindings for libdtrace Alan Maguire
2026-08-12 13:22 ` [PATCH v4 5/9] dtrace.spec: add python bindings packaging Alan Maguire
2026-08-12 13:22 ` [PATCH v4 6/9] runtest.sh: Export PYTHONPATH when running tests in-tree Alan Maguire
2026-08-12 13:22 ` [PATCH v4 7/9] test: add tests for python bindings Alan Maguire
2026-08-12 13:22 ` [PATCH v4 8/9] dtrace: Add a PCP PMDA to expose DTrace data as metrics Alan Maguire
2026-08-12 13:22 ` [PATCH v4 9/9] dtrace.spec: Add optional PCP PMDA packaging pcp-pmda-dtrace Alan Maguire
2026-08-13 21:01 ` [PATCH v4 0/9] Add python, PCP support via libdtrace interfaces Kris Van Hees
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260812132212.527871-3-alan.maguire@oracle.com \
--to=alan.maguire@oracle.com \
--cc=dtrace-devel@oss.oracle.com \
--cc=dtrace@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox