[DTrace-devel] [PATCH 02/13] Add code for quantize() aggregation function
eugene.loh at oracle.com
eugene.loh at oracle.com
Wed Dec 2 10:54:47 PST 2020
From: Eugene Loh <eugene.loh at oracle.com>
Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
bpf/Build | 1 +
bpf/agg_qbin.c | 40 +++++++++++++++++++++++
libdtrace/dt_cg.c | 75 +++++++++++++++++++++++++++++++++++++++++++-
libdtrace/dt_dlibs.c | 1 +
4 files changed, 116 insertions(+), 1 deletion(-)
create mode 100644 bpf/agg_qbin.c
diff --git a/bpf/Build b/bpf/Build
index bd7683e0..ae298f79 100644
--- a/bpf/Build
+++ b/bpf/Build
@@ -22,6 +22,7 @@ bpf_dlib_TARGET = dlibs/bpf_dlib
bpf_dlib_DIR := $(current-dir)
bpf_dlib_SRCDEPS = $(objdir)/include/.dir.stamp
bpf_dlib_SOURCES = \
+ agg_qbin.c \
get_bvar.c \
get_gvar.c set_gvar.c \
get_tvar.c set_tvar.c \
diff --git a/bpf/agg_qbin.c b/bpf/agg_qbin.c
new file mode 100644
index 00000000..741dfe27
--- /dev/null
+++ b/bpf/agg_qbin.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ */
+#include <linux/bpf.h>
+#include <stdint.h>
+#include <bpf-helpers.h>
+
+#ifndef noinline
+# define noinline __attribute__((noinline))
+#endif
+
+noinline int16_t dt_agg_qbin(int64_t val)
+{
+ int16_t off;
+ uint64_t tmp;
+
+ if (val == 0)
+ return 63;
+ if (val == 0x8000000000000000)
+ return 0;
+
+ tmp = val;
+ if (val < 0)
+ tmp *= -1;
+
+ /* now, tmp has at least one 1, while the leading bit is 0 */
+ off = 1;
+ if (tmp & 0x7fffffff00000000) { off += 32; tmp >>= 32; }
+ if (tmp & 0x00000000ffff0000) { off += 16; tmp >>= 16; }
+ if (tmp & 0x000000000000ff00) { off += 8; tmp >>= 8; }
+ if (tmp & 0x00000000000000f0) { off += 4; tmp >>= 4; }
+ if (tmp & 0x000000000000000c) { off += 2; tmp >>= 2; }
+ if (tmp & 0x0000000000000002) { off += 1; }
+
+ if (val < 0)
+ off *= -1;
+ off += 63;
+ return off;
+}
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 178f82b0..ccf475fe 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -3114,6 +3114,35 @@ dt_cg_agg_count(dt_pcb_t *pcb, dt_ident_t *aid, dt_node_t *dnp,
TRACE_REGSET(" AggCnt: End ");
}
+static void
+dt_cg_agg_quantize_impl(dt_irlist_t *dlp, dt_regset_t *drp, int dreg, int vreg, int ireg, int maxbin)
+{
+ uint_t L = dt_irlist_label(dlp);
+ int offreg;
+
+ TRACE_REGSET(" Impl: Begin");
+
+ if ((offreg = dt_regset_alloc(drp)) == -1)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+
+ /* clip to in-bounds */
+ emit(dlp, BPF_MOV_IMM(offreg, maxbin));
+ emit(dlp, BPF_BRANCH_IMM(BPF_JGT, vreg, maxbin, L));
+ emit(dlp, BPF_MOV_IMM(offreg, 0));
+ emit(dlp, BPF_BRANCH_IMM(BPF_JLT, vreg, 0, L));
+ emit(dlp, BPF_MOV_REG(offreg, vreg));
+
+ /* *(dest + 8 * off) += incr */
+ emitl(dlp, L,
+ BPF_ALU64_IMM(BPF_MUL, offreg, 8));
+ emit(dlp, BPF_ALU64_REG(BPF_ADD, offreg, dreg));
+ emit(dlp, BPF_XADD_REG(BPF_DW, offreg, 0, ireg));
+
+ dt_regset_free(drp, offreg);
+
+ TRACE_REGSET(" Impl: End ");
+}
+
static void
dt_cg_agg_llquantize(dt_pcb_t *pcb, dt_ident_t *aid, dt_node_t *dnp,
dt_irlist_t *dlp, dt_regset_t *drp)
@@ -3541,13 +3570,57 @@ static void
dt_cg_agg_quantize(dt_pcb_t *pcb, dt_ident_t *aid, dt_node_t *dnp,
dt_irlist_t *dlp, dt_regset_t *drp)
{
+ dt_ident_t *idp;
dt_node_t *incr;
- int sz = DTRACE_QUANTIZE_NBUCKETS * sizeof(uint64_t);
+ int ireg, sz = DTRACE_QUANTIZE_NBUCKETS * sizeof(uint64_t);
+
+ /*
+ * The quantize() implementation is currently hardwired for
+ * DTRACE_QUANTIZE_NBUCKETS 127
+ * DTRACE_QUANTIZE_ZEROBUCKET 63
+ * These values are defined in include/dtrace/actions_defines.h
+ */
+ assert(DTRACE_QUANTIZE_NBUCKETS == 127 &&
+ DTRACE_QUANTIZE_ZEROBUCKET == 63);
incr = dt_cg_agg_opt_incr(dnp, dnp->dn_aggfun->dn_args, "quantize", 2);
if (aid->di_offset == -1)
aid->di_offset = DT_CG_AGG_OFFSET(pcb, sz);
+
+ TRACE_REGSET(" AggQ : Begin");
+
+ dt_cg_node(dnp->dn_aggfun->dn_args, dlp, drp);
+
+ /* quantize the value to a 0-based bin # using dt_agg_qbin() */
+ if (dt_regset_xalloc_args(drp) == -1)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ emit(dlp, BPF_MOV_REG(BPF_REG_1, dnp->dn_aggfun->dn_args->dn_reg));
+ idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_agg_qbin");
+ assert(idp != NULL);
+ dt_regset_xalloc(drp, BPF_REG_0);
+ emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
+ dt_regset_free_args(drp);
+ emit(dlp, BPF_MOV_REG(dnp->dn_aggfun->dn_args->dn_reg, BPF_REG_0));
+ dt_regset_free(drp, BPF_REG_0);
+
+ if (incr == NULL) {
+ if ((ireg = dt_regset_alloc(drp)) == -1)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+
+ emit(dlp, BPF_MOV_IMM(ireg, 1));
+ } else {
+ dt_cg_node(incr, dlp, drp);
+ ireg = incr->dn_reg;
+ }
+
+ DT_CG_AGG_IMPL(aid, sz, dlp, drp, dt_cg_agg_quantize_impl,
+ dnp->dn_aggfun->dn_args->dn_reg, ireg, 126);
+
+ dt_regset_free(drp, dnp->dn_aggfun->dn_args->dn_reg);
+ dt_regset_free(drp, ireg);
+
+ TRACE_REGSET(" AggQ : End ");
}
static void
diff --git a/libdtrace/dt_dlibs.c b/libdtrace/dt_dlibs.c
index 6c6e11eb..e3ab2231 100644
--- a/libdtrace/dt_dlibs.c
+++ b/libdtrace/dt_dlibs.c
@@ -52,6 +52,7 @@ static const dt_ident_t dt_bpf_symbols[] = {
/* BPF built-in functions */
DT_BPF_SYMBOL(dt_program, DT_IDENT_FUNC),
/* BPF library (external) functions */
+ DT_BPF_SYMBOL(dt_agg_qbin, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_get_bvar, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_get_gvar, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_get_string, DT_IDENT_SYMBOL),
--
2.18.4
More information about the DTrace-devel
mailing list