Skip to content

Commit

Permalink
Add support for built-in variable walltimestamp
Browse files Browse the repository at this point in the history
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@oracle.com>
Reviewed-by: Kris Van Hees <kris.van.hees@oracle.com>
  • Loading branch information
euloh authored and kvanhees committed Jun 18, 2021
1 parent 26724bc commit dfae1d2
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 4 deletions.
3 changes: 3 additions & 0 deletions bpf/get_bvar.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
({ \
Expand Down Expand Up @@ -134,6 +135,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;
Expand Down
1 change: 1 addition & 0 deletions libdtrace/dt_bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
19 changes: 19 additions & 0 deletions libdtrace/dt_cc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2215,6 +2215,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,
Expand Down Expand Up @@ -2338,6 +2352,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)
Expand Down
1 change: 1 addition & 0 deletions libdtrace/dt_dlibs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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, }
};
Expand Down
3 changes: 1 addition & 2 deletions test/demo/act/time.d
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion test/unittest/printa/tst.walltimestamp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion test/unittest/variables/bvar/tst.walltimestamp.d
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
29 changes: 29 additions & 0 deletions test/unittest/variables/bvar/tst.walltimestamp2.d
Original file line number Diff line number Diff line change
@@ -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);
}
1 change: 1 addition & 0 deletions test/unittest/variables/bvar/tst.walltimestamp2.r
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
success
40 changes: 40 additions & 0 deletions test/unittest/variables/bvar/tst.walltimestamp2.r.p
Original file line number Diff line number Diff line change
@@ -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;
}

0 comments on commit dfae1d2

Please sign in to comment.