Skip to content

Commit 0b6bc3d

Browse files
committed
Merge tag 'trace-latency-v7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace
Pull tracing latency update from Steven Rostedt: - Add TIMERLAT_ALIGN osnoise option Add a timer alignment option for timerlat that makes it work like the cyclictest -A option. timelat creates threads to test the latency of the kernel. The alignment option will have these threads trigger at the alignment offsets from each other. Instead of having each thread wake up at the exact same time, if the alignment is set to "20" each thread will wake up at 20 microseconds from the previous one. * tag 'trace-latency-v7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: tracing/osnoise: Add option to align tlat threads
2 parents cb30bf8 + 4245bf4 commit 0b6bc3d

1 file changed

Lines changed: 53 additions & 1 deletion

File tree

kernel/trace/trace_osnoise.c

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ enum osnoise_options_index {
5858
OSN_PANIC_ON_STOP,
5959
OSN_PREEMPT_DISABLE,
6060
OSN_IRQ_DISABLE,
61+
OSN_TIMERLAT_ALIGN,
6162
OSN_MAX
6263
};
6364

@@ -66,7 +67,8 @@ static const char * const osnoise_options_str[OSN_MAX] = {
6667
"OSNOISE_WORKLOAD",
6768
"PANIC_ON_STOP",
6869
"OSNOISE_PREEMPT_DISABLE",
69-
"OSNOISE_IRQ_DISABLE" };
70+
"OSNOISE_IRQ_DISABLE",
71+
"TIMERLAT_ALIGN" };
7072

7173
#define OSN_DEFAULT_OPTIONS 0x2
7274
static unsigned long osnoise_options = OSN_DEFAULT_OPTIONS;
@@ -250,6 +252,11 @@ struct timerlat_variables {
250252

251253
static DEFINE_PER_CPU(struct timerlat_variables, per_cpu_timerlat_var);
252254

255+
/*
256+
* timerlat wake-up offset for next thread with TIMERLAT_ALIGN set.
257+
*/
258+
static atomic64_t align_next;
259+
253260
/*
254261
* this_cpu_tmr_var - Return the per-cpu timerlat_variables on its relative CPU
255262
*/
@@ -268,6 +275,7 @@ static inline void tlat_var_reset(void)
268275

269276
/* Synchronize with the timerlat interfaces */
270277
mutex_lock(&interface_lock);
278+
271279
/*
272280
* So far, all the values are initialized as 0, so
273281
* zeroing the structure is perfect.
@@ -278,6 +286,12 @@ static inline void tlat_var_reset(void)
278286
hrtimer_cancel(&tlat_var->timer);
279287
memset(tlat_var, 0, sizeof(*tlat_var));
280288
}
289+
/*
290+
* Reset also align_next, to be filled by a new offset by the first timerlat
291+
* thread that wakes up, if TIMERLAT_ALIGN is set.
292+
*/
293+
atomic64_set(&align_next, 0);
294+
281295
mutex_unlock(&interface_lock);
282296
}
283297
#else /* CONFIG_TIMERLAT_TRACER */
@@ -326,6 +340,7 @@ static struct osnoise_data {
326340
u64 stop_tracing_total; /* stop trace in the final operation (report/thread) */
327341
#ifdef CONFIG_TIMERLAT_TRACER
328342
u64 timerlat_period; /* timerlat period */
343+
u64 timerlat_align_us; /* timerlat alignment */
329344
u64 print_stack; /* print IRQ stack if total > */
330345
int timerlat_tracer; /* timerlat tracer */
331346
#endif
@@ -338,6 +353,7 @@ static struct osnoise_data {
338353
#ifdef CONFIG_TIMERLAT_TRACER
339354
.print_stack = 0,
340355
.timerlat_period = DEFAULT_TIMERLAT_PERIOD,
356+
.timerlat_align_us = 0,
341357
.timerlat_tracer = 0,
342358
#endif
343359
};
@@ -1829,6 +1845,26 @@ static int wait_next_period(struct timerlat_variables *tlat)
18291845
*/
18301846
tlat->abs_period = (u64) ktime_to_ns(next_abs_period);
18311847

1848+
/*
1849+
* Align thread in the first cycle on each CPU to the set alignment
1850+
* if TIMERLAT_ALIGN is set.
1851+
*
1852+
* This is done by using an atomic64_t to store the next absolute period.
1853+
* The first thread that wakes up will set the atomic64_t to its
1854+
* absolute period, and the other threads will increment it by
1855+
* the alignment value.
1856+
*/
1857+
if (test_bit(OSN_TIMERLAT_ALIGN, &osnoise_options) && !tlat->count
1858+
&& atomic64_cmpxchg_relaxed(&align_next, 0, tlat->abs_period)) {
1859+
/*
1860+
* A thread has already set align_next, use it and increment it
1861+
* to be used by the next thread that wakes up after this one.
1862+
*/
1863+
tlat->abs_period = atomic64_add_return_relaxed(
1864+
osnoise_data.timerlat_align_us * 1000, &align_next);
1865+
next_abs_period = ns_to_ktime(tlat->abs_period);
1866+
}
1867+
18321868
/*
18331869
* If the new abs_period is in the past, skip the activation.
18341870
*/
@@ -2650,6 +2686,17 @@ static struct trace_min_max_param timerlat_period = {
26502686
.min = &timerlat_min_period,
26512687
};
26522688

2689+
/*
2690+
* osnoise/timerlat_align_us: align the first wakeup of all timerlat
2691+
* threads to a common boundary (in us). 0 means disabled.
2692+
*/
2693+
static struct trace_min_max_param timerlat_align_us = {
2694+
.lock = &interface_lock,
2695+
.val = &osnoise_data.timerlat_align_us,
2696+
.max = NULL,
2697+
.min = NULL,
2698+
};
2699+
26532700
static const struct file_operations timerlat_fd_fops = {
26542701
.open = timerlat_fd_open,
26552702
.read = timerlat_fd_read,
@@ -2746,6 +2793,11 @@ static int init_timerlat_tracefs(struct dentry *top_dir)
27462793
if (!tmp)
27472794
return -ENOMEM;
27482795

2796+
tmp = tracefs_create_file("timerlat_align_us", TRACE_MODE_WRITE, top_dir,
2797+
&timerlat_align_us, &trace_min_max_fops);
2798+
if (!tmp)
2799+
return -ENOMEM;
2800+
27492801
retval = osnoise_create_cpu_timerlat_fd(top_dir);
27502802
if (retval)
27512803
return retval;

0 commit comments

Comments
 (0)