Download raw body.
dt: Count skipped clock cycles as dropped events
If the clock interrupt advances for more than one tick, we obviously
lost a number of clock ticks. That might happen in a virtual machine
that does not get scheduled in time. There is no point in creating a
cluster of events with basically the same timestamp and identical stack
traces. Generate only one event instead and drop all skipped ticks.
- Christian
---
sys/dev/dt/dt_dev.c | 12 ++++++++++--
sys/dev/dt/dt_prov_profile.c | 17 ++++++++++-------
sys/dev/dt/dtvar.h | 1 +
3 files changed, 21 insertions(+), 9 deletions(-)
diff --git a/sys/dev/dt/dt_dev.c b/sys/dev/dt/dt_dev.c
index 75fbbba6a575..286bda80992d 100644
--- a/sys/dev/dt/dt_dev.c
+++ b/sys/dev/dt/dt_dev.c
@@ -725,6 +725,15 @@ dt_pcb_purge(struct dt_pcb_list *plist)
}
}
+void
+dt_pcb_ring_drop(struct dt_pcb *dp, unsigned int drop)
+{
+ struct dt_cpubuf *dc = &dp->dp_sc->ds_cpu[cpu_number()];
+
+ dc->dc_dropevt += drop;
+ membar_producer();
+}
+
/*
* Get a reference to the next free event state from the ring.
*/
@@ -747,8 +756,7 @@ dt_pcb_ring_get(struct dt_pcb *dp, int profiling)
distance = prod - cons;
if (distance == 1 || distance == (1 - DT_EVTRING_SIZE)) {
/* read(2) isn't finished */
- dc->dc_dropevt++;
- membar_producer();
+ dt_pcb_ring_drop(dp, 1);
dc->dc_inevt = 0;
return NULL;
diff --git a/sys/dev/dt/dt_prov_profile.c b/sys/dev/dt/dt_prov_profile.c
index 62900152e147..5e4d9f1a2081 100644
--- a/sys/dev/dt/dt_prov_profile.c
+++ b/sys/dev/dt/dt_prov_profile.c
@@ -101,15 +101,18 @@ dt_prov_profile_alloc(struct dt_probe *dtp, struct dt_softc *sc,
void
dt_clock(struct clockrequest *cr, void *cf, void *arg)
{
- uint64_t count, i;
+ uint64_t count;
struct dt_evt *dtev;
struct dt_pcb *dp = arg;
count = clockrequest_advance(cr, dp->dp_nsecs);
- for (i = 0; i < count; i++) {
- dtev = dt_pcb_ring_get(dp, 1);
- if (dtev == NULL)
- return;
- dt_pcb_ring_consume(dp, dtev);
- }
+ if (count == 0)
+ return;
+ else if (count > 1)
+ dt_pcb_ring_drop(dp, count - 1);
+
+ dtev = dt_pcb_ring_get(dp, 1);
+ if (dtev == NULL)
+ return;
+ dt_pcb_ring_consume(dp, dtev);
}
diff --git a/sys/dev/dt/dtvar.h b/sys/dev/dt/dtvar.h
index c6cfa7f66b3b..a1f6037e3233 100644
--- a/sys/dev/dt/dtvar.h
+++ b/sys/dev/dt/dtvar.h
@@ -179,6 +179,7 @@ struct dt_pcb *dt_pcb_alloc(struct dt_probe *, struct dt_softc *);
void dt_pcb_free(struct dt_pcb *);
void dt_pcb_purge(struct dt_pcb_list *);
+void dt_pcb_ring_drop(struct dt_pcb *, unsigned int);
struct dt_evt *dt_pcb_ring_get(struct dt_pcb *, int);
void dt_pcb_ring_consume(struct dt_pcb *, struct dt_evt *);
--
2.34.1
dt: Count skipped clock cycles as dropped events