[DTrace-devel] [PATCH v2] Add support for built-in variable walltimestamp

eugene.loh at oracle.com eugene.loh at oracle.com
Mon Jun 14 14:52:01 PDT 2021


From: Eugene Loh <eugene.loh at oracle.com>

In the pre-compiled get_bvar() function, 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                                |  6 +++
 libdtrace/dt_bpf.h                            |  2 +
 libdtrace/dt_cc.c                             | 24 +++++++++++
 libdtrace/dt_dlibs.c                          |  2 +
 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, 106 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..3d6744c4 100644
--- a/bpf/get_bvar.c
+++ b/bpf/get_bvar.c
@@ -27,6 +27,8 @@ extern struct bpf_map_def state;
 extern uint64_t STBSZ;
 extern uint64_t STKOFF;
 extern uint64_t STKSIZ;
+extern uint64_t BOOTTIMEHI;
+extern uint64_t BOOTTIMELO;
 
 #define error(dctx, fault, illval) \
 	({ \
@@ -167,6 +169,10 @@ 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) &BOOTTIMEHI) << 32)
+		    + ((uint64_t) &BOOTTIMELO);
 	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..96731095 100644
--- a/libdtrace/dt_bpf.h
+++ b/libdtrace/dt_bpf.h
@@ -25,6 +25,8 @@ extern "C" {
 #define DT_CONST_STBSZ	5
 #define DT_CONST_STKOFF	6
 #define DT_CONST_STKSIZ	7
+#define DT_CONST_BOOTTIMEHI	8
+#define DT_CONST_BOOTTIMELO	9
 
 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 d69e2d04..f8386e24 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,16 @@ 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_BOOTTIMEHI:
+				if (boottime == 0 && get_boottime())
+					return -1;
+				nrp->dofr_data = boottime >> 32;
+				continue;
+			case DT_CONST_BOOTTIMELO:
+				if (boottime == 0 && get_boottime())
+					return -1;
+				nrp->dofr_data = boottime & 0xffffffff;
+				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..8a82063f 100644
--- a/libdtrace/dt_dlibs.c
+++ b/libdtrace/dt_dlibs.c
@@ -80,6 +80,8 @@ 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(BOOTTIMEHI, DT_IDENT_SCALAR, DT_CONST_BOOTTIMEHI),
+	DT_BPF_SYMBOL_ID(BOOTTIMELO, DT_IDENT_SCALAR, DT_CONST_BOOTTIMELO),
 	/* 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