Add a small primitive that records, per automaton edge, how long the monitor dwelled before taking it with a count, a sum and a maximum.
The counters are per-CPU and lock-free, so a monitor's hot path can update them without disabling interrupts and without perturbing the very latency being measured. Signed-off-by: Tobias Schaffner <[email protected]> --- MAINTAINERS | 1 + include/linux/rv_edge_stat.h | 45 ++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 include/linux/rv_edge_stat.h diff --git a/MAINTAINERS b/MAINTAINERS index 8014b9f8253e..04589dda0873 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23654,6 +23654,7 @@ L: [email protected] S: Maintained F: Documentation/trace/rv/ F: include/linux/rv.h +F: include/linux/rv_edge_stat.h F: include/rv/ F: kernel/trace/rv/ F: tools/testing/selftests/verification/ diff --git a/include/linux/rv_edge_stat.h b/include/linux/rv_edge_stat.h new file mode 100644 index 000000000000..751de8074dcc --- /dev/null +++ b/include/linux/rv_edge_stat.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Per-edge dwell-time statistics for RV monitors. + * + * Copyright (C) 2026 Siemens AG + * Author: Tobias Schaffner <[email protected]> + */ +#ifndef _LINUX_RV_EDGE_STAT_H +#define _LINUX_RV_EDGE_STAT_H + +#include <linux/compiler.h> +#include <linux/types.h> +#include <asm/local64.h> + +/* + * Per-CPU counters kept in local64_t so accounting is safe against interrupt + * and NMI nesting on the owning CPU without disabling interrupts -- the same + * approach the trace ring buffer uses. Only the owning CPU writes. + */ +struct rv_edge_stat { + local64_t count; + local64_t sum_ns; + local64_t max_ns; +}; + +static __always_inline +void rv_edge_stat_account(struct rv_edge_stat *s, u64 dwell_ns) +{ + s64 max; + + local64_inc(&s->count); + local64_add(dwell_ns, &s->sum_ns); + + /* Keep the largest dwell; retry only if a nested update raced us. */ + max = local64_read(&s->max_ns); + while (dwell_ns > (u64)max) { + s64 prev = local64_cmpxchg(&s->max_ns, max, dwell_ns); + + if (prev == max) + break; + max = prev; + } +} + +#endif /* _LINUX_RV_EDGE_STAT_H */ -- 2.43.0
