[DTrace-devel] [PATCH v3] Add support for built-in variable walltimestamp
eugene.loh at oracle.com
eugene.loh at oracle.com
Tue Jun 15 11:43:58 PDT 2021
From: Eugene Loh <eugene.loh at oracle.com>
In the pre-compiled function get_bvar(), use bpf_ktime_get_ns() to
get the time (in nsec) since boot. This value is adjusted by adding
the POSIX time when the system was booted.
A few more walltimestamp tests pass now, but existing walltimestamp
tests are rather lenient. Add a new, more stringent test. In particular,
timestamp is supposed to be fixed for an entire clause while walltimestamp
is fresh with every call.
Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
bpf/get_bvar.c | 3 ++
libdtrace/dt_bpf.h | 1 +
libdtrace/dt_cc.c | 19 +++++++++
libdtrace/dt_dlibs.c | 1 +
test/demo/act/time.d | 3 +-
test/unittest/printa/tst.walltimestamp.sh | 2 +-
.../variables/bvar/tst.walltimestamp.d | 1 -
.../variables/bvar/tst.walltimestamp2.d | 29 ++++++++++++++
.../variables/bvar/tst.walltimestamp2.r | 1 +
.../variables/bvar/tst.walltimestamp2.r.p | 40 +++++++++++++++++++
10 files changed, 96 insertions(+), 4 deletions(-)
create mode 100644 test/unittest/variables/bvar/tst.walltimestamp2.d
create mode 100644 test/unittest/variables/bvar/tst.walltimestamp2.r
create mode 100755 test/unittest/variables/bvar/tst.walltimestamp2.r.p
diff --git a/bpf/get_bvar.c b/bpf/get_bvar.c
index e92287aa..e28918cc 100644
--- a/bpf/get_bvar.c
+++ b/bpf/get_bvar.c
@@ -27,6 +27,7 @@ extern struct bpf_map_def state;
extern uint64_t STBSZ;
extern uint64_t STKOFF;
extern uint64_t STKSIZ;
+extern uint64_t BOOTTM;
#define error(dctx, fault, illval) \
({ \
@@ -167,6 +168,8 @@ noinline uint64_t dt_get_bvar(dt_dctx_t *dctx, uint32_t id)
return val & 0x00000000ffffffffUL;
}
+ case DIF_VAR_WALLTIMESTAMP:
+ return bpf_ktime_get_ns() + ((uint64_t) &BOOTTM);
case DIF_VAR_PPID: {
uint64_t ptr;
int32_t val = -1;
diff --git a/libdtrace/dt_bpf.h b/libdtrace/dt_bpf.h
index 3afc95fa..dcc82b80 100644
--- a/libdtrace/dt_bpf.h
+++ b/libdtrace/dt_bpf.h
@@ -25,6 +25,7 @@ extern "C" {
#define DT_CONST_STBSZ 5
#define DT_CONST_STKOFF 6
#define DT_CONST_STKSIZ 7
+#define DT_CONST_BOOTTM 8
extern int perf_event_open(struct perf_event_attr *attr, pid_t pid, int cpu,
int group_fd, unsigned long flags);
diff --git a/libdtrace/dt_cc.c b/libdtrace/dt_cc.c
index 009f9e64..70e461e3 100644
--- a/libdtrace/dt_cc.c
+++ b/libdtrace/dt_cc.c
@@ -2211,6 +2211,20 @@ dt_link_layout(dtrace_hdl_t *dtp, const dtrace_difo_t *dp, uint_t *pcp,
return pc;
}
+static uint64_t boottime = 0;
+static int get_boottime() {
+ struct timespec t_real, t_boot;
+
+ if (clock_gettime(CLOCK_REALTIME, &t_real))
+ return -1;
+ if (clock_gettime(CLOCK_MONOTONIC, &t_boot))
+ return -1;
+ boottime = t_real.tv_sec - t_boot.tv_sec;
+ boottime *= 1000000000;
+ boottime += t_real.tv_nsec - t_boot.tv_nsec;
+ return 0;
+}
+
static int
dt_link_construct(dtrace_hdl_t *dtp, const dt_probe_t *prp, dtrace_difo_t *dp,
dt_ident_t *idp, const dtrace_difo_t *sdp, dt_strtab_t *stab,
@@ -2334,6 +2348,11 @@ dt_link_construct(dtrace_hdl_t *dtp, const dt_probe_t *prp, dtrace_difo_t *dp,
nrp->dofr_data = sizeof(uint64_t)
* dtp->dt_options[DTRACEOPT_MAXFRAMES];
continue;
+ case DT_CONST_BOOTTM:
+ if (boottime == 0 && get_boottime())
+ return -1;
+ nrp->dofr_data = boottime;
+ continue;
default:
/* probe name -> value is probe id */
if (strchr(idp->di_name, ':') != NULL)
diff --git a/libdtrace/dt_dlibs.c b/libdtrace/dt_dlibs.c
index 10886adb..35a18596 100644
--- a/libdtrace/dt_dlibs.c
+++ b/libdtrace/dt_dlibs.c
@@ -80,6 +80,7 @@ static const dt_ident_t dt_bpf_symbols[] = {
DT_BPF_SYMBOL_ID(STBSZ, DT_IDENT_SCALAR, DT_CONST_STBSZ),
DT_BPF_SYMBOL_ID(STKOFF, DT_IDENT_SCALAR, DT_CONST_STKOFF),
DT_BPF_SYMBOL_ID(STKSIZ, DT_IDENT_SCALAR, DT_CONST_STKSIZ),
+ DT_BPF_SYMBOL_ID(BOOTTM, DT_IDENT_SCALAR, DT_CONST_BOOTTM),
/* End-of-list marker */
{ NULL, }
};
diff --git a/test/demo/act/time.d b/test/demo/act/time.d
index 61c97b30..76f2d22f 100644
--- a/test/demo/act/time.d
+++ b/test/demo/act/time.d
@@ -1,11 +1,10 @@
/*
* Oracle Linux DTrace.
- * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2021, 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.
*/
-/* @@xfail: dtv2 */
/* @@trigger: none */
#pragma D option quiet
diff --git a/test/unittest/printa/tst.walltimestamp.sh b/test/unittest/printa/tst.walltimestamp.sh
index aaa627bc..8037ccab 100755
--- a/test/unittest/printa/tst.walltimestamp.sh
+++ b/test/unittest/printa/tst.walltimestamp.sh
@@ -5,7 +5,7 @@
# Licensed under the Universal Permissive License v 1.0 as shown at
# http://oss.oracle.com/licenses/upl.
#
-# @@xfail: dtv2
+
if [ $# != 1 ]; then
echo expected one argument: '<'dtrace-path'>'
exit 2
diff --git a/test/unittest/variables/bvar/tst.walltimestamp.d b/test/unittest/variables/bvar/tst.walltimestamp.d
index 4797287d..95eed54a 100644
--- a/test/unittest/variables/bvar/tst.walltimestamp.d
+++ b/test/unittest/variables/bvar/tst.walltimestamp.d
@@ -4,7 +4,6 @@
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
-/* @@xfail: dtv2 */
/*
* ASSERTION: The 'walltimestamp' variable can be accessed and is not -1.
diff --git a/test/unittest/variables/bvar/tst.walltimestamp2.d b/test/unittest/variables/bvar/tst.walltimestamp2.d
new file mode 100644
index 00000000..98f142d9
--- /dev/null
+++ b/test/unittest/variables/bvar/tst.walltimestamp2.d
@@ -0,0 +1,29 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2021, 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.
+ */
+
+#pragma D option quiet
+#pragma D option destructive
+
+BEGIN {
+ /* baseline time stamp from system("date") */
+ system("date +'%%s.%%N'");
+
+ /* get five consecutive time stamps from DTrace */
+ t1 = walltimestamp;
+ t2 = walltimestamp;
+ t3 = walltimestamp;
+ t4 = walltimestamp;
+ t5 = walltimestamp;
+
+ /* report the first time stamp and the subsequent deltas */
+ printf("%d\n", t1);
+ printf("%d\n", t2 - t1);
+ printf("%d\n", t3 - t2);
+ printf("%d\n", t4 - t3);
+ printf("%d\n", t5 - t4);
+ exit(0);
+}
diff --git a/test/unittest/variables/bvar/tst.walltimestamp2.r b/test/unittest/variables/bvar/tst.walltimestamp2.r
new file mode 100644
index 00000000..2e9ba477
--- /dev/null
+++ b/test/unittest/variables/bvar/tst.walltimestamp2.r
@@ -0,0 +1 @@
+success
diff --git a/test/unittest/variables/bvar/tst.walltimestamp2.r.p b/test/unittest/variables/bvar/tst.walltimestamp2.r.p
new file mode 100755
index 00000000..48652ded
--- /dev/null
+++ b/test/unittest/variables/bvar/tst.walltimestamp2.r.p
@@ -0,0 +1,40 @@
+#!/usr/bin/gawk -f
+#
+# Oracle Linux DTrace.
+# Copyright (c) 2021, 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.
+
+{
+ # read the value generated by system("date")
+ t0 = $1; getline;
+
+ # read a walltimestamp value from DTrace
+ t1 = $1; getline;
+
+ # read a few walltimestamp deltas from DTrace
+ d2 = $1; getline;
+ d3 = $1; getline;
+ d4 = $1; getline;
+ d5 = $1;
+
+ # check that the deltas are all positive
+ if (d2 <= 0 ||
+ d3 <= 0 ||
+ d4 <= 0 ||
+ d5 <= 0) print "ERROR: walltimestamp did not advance.";
+
+ # check that the deltas are all under 0.2 seconds
+ if (d2 > 200000000 ||
+ d3 > 200000000 ||
+ d4 > 200000000 ||
+ d5 > 200000000) print "ERROR: walltimestamp delta is high.";
+
+ # check walltimestamp against system("date")
+ t_error = 1.e-9 * t1 - t0;
+ if (t_error < 0) t_error *= -1;
+ if (t_error > 0.2) print "ERROR: walltimestamp and system(date) disagree.";
+
+ print "success";
+ exit 0;
+}
--
2.18.4
More information about the DTrace-devel
mailing list