File Index
Files and directories
Sign in
FILE

timerlat.bpf.c

File preview with syntax highlighting.

linux-6.19.14/tools/tracing/rtla/src/timerlat.bpf.c C
  1// SPDX-License-Identifier: GPL-2.0
  2#include <linux/bpf.h>
  3#include <bpf/bpf_tracing.h>
  4#include <stdbool.h>
  5#include "timerlat_bpf.h"
  6
  7#define nosubprog __always_inline
  8#define MAX_ENTRIES_DEFAULT 4096
  9
 10char LICENSE[] SEC("license") = "GPL";
 11
 12struct trace_event_raw_timerlat_sample {
 13	unsigned long long timer_latency;
 14	int context;
 15} __attribute__((preserve_access_index));
 16
 17struct {
 18	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
 19	__uint(max_entries, MAX_ENTRIES_DEFAULT);
 20	__type(key, unsigned int);
 21	__type(value, unsigned long long);
 22} hist_irq SEC(".maps"), hist_thread SEC(".maps"), hist_user SEC(".maps");
 23
 24struct {
 25	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
 26	__uint(max_entries, SUMMARY_FIELD_N);
 27	__type(key, unsigned int);
 28	__type(value, unsigned long long);
 29} summary_irq SEC(".maps"), summary_thread SEC(".maps"), summary_user SEC(".maps");
 30
 31struct {
 32	__uint(type, BPF_MAP_TYPE_ARRAY);
 33	__uint(max_entries, 1);
 34	__type(key, unsigned int);
 35	__type(value, unsigned long long);
 36} stop_tracing SEC(".maps");
 37
 38struct {
 39	__uint(type, BPF_MAP_TYPE_RINGBUF);
 40	__uint(max_entries, 1);
 41} signal_stop_tracing SEC(".maps");
 42
 43/* Params to be set by rtla */
 44const volatile int bucket_size = 1;
 45const volatile int output_divisor = 1000;
 46const volatile int entries = 256;
 47const volatile int irq_threshold;
 48const volatile int thread_threshold;
 49const volatile bool aa_only;
 50
 51nosubprog unsigned long long map_get(void *map,
 52				     unsigned int key)
 53{
 54	unsigned long long *value_ptr;
 55
 56	value_ptr = bpf_map_lookup_elem(map, &key);
 57
 58	return !value_ptr ? 0 : *value_ptr;
 59}
 60
 61nosubprog void map_set(void *map,
 62		       unsigned int key,
 63		       unsigned long long value)
 64{
 65	bpf_map_update_elem(map, &key, &value, BPF_ANY);
 66}
 67
 68nosubprog void map_increment(void *map,
 69			     unsigned int key)
 70{
 71	map_set(map, key, map_get(map, key) + 1);
 72}
 73
 74nosubprog void update_main_hist(void *map,
 75				int bucket)
 76{
 77	if (entries == 0)
 78		/* No histogram */
 79		return;
 80
 81	if (bucket >= entries)
 82		/* Overflow */
 83		return;
 84
 85	map_increment(map, bucket);
 86}
 87
 88nosubprog void update_summary(void *map,
 89			      unsigned long long latency,
 90			      int bucket)
 91{
 92	if (aa_only)
 93		/* Auto-analysis only, nothing to be done here */
 94		return;
 95
 96	map_set(map, SUMMARY_CURRENT, latency);
 97
 98	if (bucket >= entries)
 99		/* Overflow */
100		map_increment(map, SUMMARY_OVERFLOW);
101
102	if (latency > map_get(map, SUMMARY_MAX))
103		map_set(map, SUMMARY_MAX, latency);
104
105	if (latency < map_get(map, SUMMARY_MIN) || map_get(map, SUMMARY_COUNT) == 0)
106		map_set(map, SUMMARY_MIN, latency);
107
108	map_increment(map, SUMMARY_COUNT);
109	map_set(map, SUMMARY_SUM, map_get(map, SUMMARY_SUM) + latency);
110}
111
112nosubprog void set_stop_tracing(void)
113{
114	int value = 0;
115
116	/* Suppress further sample processing */
117	map_set(&stop_tracing, 0, 1);
118
119	/* Signal to userspace */
120	bpf_ringbuf_output(&signal_stop_tracing, &value, sizeof(value), 0);
121}
122
123SEC("tp/osnoise/timerlat_sample")
124int handle_timerlat_sample(struct trace_event_raw_timerlat_sample *tp_args)
125{
126	unsigned long long latency, latency_us;
127	int bucket;
128
129	if (map_get(&stop_tracing, 0))
130		return 0;
131
132	latency = tp_args->timer_latency / output_divisor;
133	latency_us = tp_args->timer_latency / 1000;
134	bucket = latency / bucket_size;
135
136	if (tp_args->context == 0) {
137		update_main_hist(&hist_irq, bucket);
138		update_summary(&summary_irq, latency, bucket);
139
140		if (irq_threshold != 0 && latency_us >= irq_threshold)
141			set_stop_tracing();
142	} else if (tp_args->context == 1) {
143		update_main_hist(&hist_thread, bucket);
144		update_summary(&summary_thread, latency, bucket);
145
146		if (thread_threshold != 0 && latency_us >= thread_threshold)
147			set_stop_tracing();
148	} else {
149		update_main_hist(&hist_user, bucket);
150		update_summary(&summary_user, latency, bucket);
151
152		if (thread_threshold != 0 && latency_us >= thread_threshold)
153			set_stop_tracing();
154	}
155
156	return 0;
157}
~/ Read-only file preview.