mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
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
This commit is contained in:
@@ -58,6 +58,7 @@ enum osnoise_options_index {
|
|||||||
OSN_PANIC_ON_STOP,
|
OSN_PANIC_ON_STOP,
|
||||||
OSN_PREEMPT_DISABLE,
|
OSN_PREEMPT_DISABLE,
|
||||||
OSN_IRQ_DISABLE,
|
OSN_IRQ_DISABLE,
|
||||||
|
OSN_TIMERLAT_ALIGN,
|
||||||
OSN_MAX
|
OSN_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -66,7 +67,8 @@ static const char * const osnoise_options_str[OSN_MAX] = {
|
|||||||
"OSNOISE_WORKLOAD",
|
"OSNOISE_WORKLOAD",
|
||||||
"PANIC_ON_STOP",
|
"PANIC_ON_STOP",
|
||||||
"OSNOISE_PREEMPT_DISABLE",
|
"OSNOISE_PREEMPT_DISABLE",
|
||||||
"OSNOISE_IRQ_DISABLE" };
|
"OSNOISE_IRQ_DISABLE",
|
||||||
|
"TIMERLAT_ALIGN" };
|
||||||
|
|
||||||
#define OSN_DEFAULT_OPTIONS 0x2
|
#define OSN_DEFAULT_OPTIONS 0x2
|
||||||
static unsigned long osnoise_options = OSN_DEFAULT_OPTIONS;
|
static unsigned long osnoise_options = OSN_DEFAULT_OPTIONS;
|
||||||
@@ -250,6 +252,11 @@ struct timerlat_variables {
|
|||||||
|
|
||||||
static DEFINE_PER_CPU(struct timerlat_variables, per_cpu_timerlat_var);
|
static DEFINE_PER_CPU(struct timerlat_variables, per_cpu_timerlat_var);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* timerlat wake-up offset for next thread with TIMERLAT_ALIGN set.
|
||||||
|
*/
|
||||||
|
static atomic64_t align_next;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* this_cpu_tmr_var - Return the per-cpu timerlat_variables on its relative CPU
|
* this_cpu_tmr_var - Return the per-cpu timerlat_variables on its relative CPU
|
||||||
*/
|
*/
|
||||||
@@ -268,6 +275,7 @@ static inline void tlat_var_reset(void)
|
|||||||
|
|
||||||
/* Synchronize with the timerlat interfaces */
|
/* Synchronize with the timerlat interfaces */
|
||||||
mutex_lock(&interface_lock);
|
mutex_lock(&interface_lock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* So far, all the values are initialized as 0, so
|
* So far, all the values are initialized as 0, so
|
||||||
* zeroing the structure is perfect.
|
* zeroing the structure is perfect.
|
||||||
@@ -278,6 +286,12 @@ static inline void tlat_var_reset(void)
|
|||||||
hrtimer_cancel(&tlat_var->timer);
|
hrtimer_cancel(&tlat_var->timer);
|
||||||
memset(tlat_var, 0, sizeof(*tlat_var));
|
memset(tlat_var, 0, sizeof(*tlat_var));
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Reset also align_next, to be filled by a new offset by the first timerlat
|
||||||
|
* thread that wakes up, if TIMERLAT_ALIGN is set.
|
||||||
|
*/
|
||||||
|
atomic64_set(&align_next, 0);
|
||||||
|
|
||||||
mutex_unlock(&interface_lock);
|
mutex_unlock(&interface_lock);
|
||||||
}
|
}
|
||||||
#else /* CONFIG_TIMERLAT_TRACER */
|
#else /* CONFIG_TIMERLAT_TRACER */
|
||||||
@@ -326,6 +340,7 @@ static struct osnoise_data {
|
|||||||
u64 stop_tracing_total; /* stop trace in the final operation (report/thread) */
|
u64 stop_tracing_total; /* stop trace in the final operation (report/thread) */
|
||||||
#ifdef CONFIG_TIMERLAT_TRACER
|
#ifdef CONFIG_TIMERLAT_TRACER
|
||||||
u64 timerlat_period; /* timerlat period */
|
u64 timerlat_period; /* timerlat period */
|
||||||
|
u64 timerlat_align_us; /* timerlat alignment */
|
||||||
u64 print_stack; /* print IRQ stack if total > */
|
u64 print_stack; /* print IRQ stack if total > */
|
||||||
int timerlat_tracer; /* timerlat tracer */
|
int timerlat_tracer; /* timerlat tracer */
|
||||||
#endif
|
#endif
|
||||||
@@ -338,6 +353,7 @@ static struct osnoise_data {
|
|||||||
#ifdef CONFIG_TIMERLAT_TRACER
|
#ifdef CONFIG_TIMERLAT_TRACER
|
||||||
.print_stack = 0,
|
.print_stack = 0,
|
||||||
.timerlat_period = DEFAULT_TIMERLAT_PERIOD,
|
.timerlat_period = DEFAULT_TIMERLAT_PERIOD,
|
||||||
|
.timerlat_align_us = 0,
|
||||||
.timerlat_tracer = 0,
|
.timerlat_tracer = 0,
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@@ -1829,6 +1845,26 @@ static int wait_next_period(struct timerlat_variables *tlat)
|
|||||||
*/
|
*/
|
||||||
tlat->abs_period = (u64) ktime_to_ns(next_abs_period);
|
tlat->abs_period = (u64) ktime_to_ns(next_abs_period);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Align thread in the first cycle on each CPU to the set alignment
|
||||||
|
* if TIMERLAT_ALIGN is set.
|
||||||
|
*
|
||||||
|
* This is done by using an atomic64_t to store the next absolute period.
|
||||||
|
* The first thread that wakes up will set the atomic64_t to its
|
||||||
|
* absolute period, and the other threads will increment it by
|
||||||
|
* the alignment value.
|
||||||
|
*/
|
||||||
|
if (test_bit(OSN_TIMERLAT_ALIGN, &osnoise_options) && !tlat->count
|
||||||
|
&& atomic64_cmpxchg_relaxed(&align_next, 0, tlat->abs_period)) {
|
||||||
|
/*
|
||||||
|
* A thread has already set align_next, use it and increment it
|
||||||
|
* to be used by the next thread that wakes up after this one.
|
||||||
|
*/
|
||||||
|
tlat->abs_period = atomic64_add_return_relaxed(
|
||||||
|
osnoise_data.timerlat_align_us * 1000, &align_next);
|
||||||
|
next_abs_period = ns_to_ktime(tlat->abs_period);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the new abs_period is in the past, skip the activation.
|
* If the new abs_period is in the past, skip the activation.
|
||||||
*/
|
*/
|
||||||
@@ -2650,6 +2686,17 @@ static struct trace_min_max_param timerlat_period = {
|
|||||||
.min = &timerlat_min_period,
|
.min = &timerlat_min_period,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* osnoise/timerlat_align_us: align the first wakeup of all timerlat
|
||||||
|
* threads to a common boundary (in us). 0 means disabled.
|
||||||
|
*/
|
||||||
|
static struct trace_min_max_param timerlat_align_us = {
|
||||||
|
.lock = &interface_lock,
|
||||||
|
.val = &osnoise_data.timerlat_align_us,
|
||||||
|
.max = NULL,
|
||||||
|
.min = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct file_operations timerlat_fd_fops = {
|
static const struct file_operations timerlat_fd_fops = {
|
||||||
.open = timerlat_fd_open,
|
.open = timerlat_fd_open,
|
||||||
.read = timerlat_fd_read,
|
.read = timerlat_fd_read,
|
||||||
@@ -2746,6 +2793,11 @@ static int init_timerlat_tracefs(struct dentry *top_dir)
|
|||||||
if (!tmp)
|
if (!tmp)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
tmp = tracefs_create_file("timerlat_align_us", TRACE_MODE_WRITE, top_dir,
|
||||||
|
&timerlat_align_us, &trace_min_max_fops);
|
||||||
|
if (!tmp)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
retval = osnoise_create_cpu_timerlat_fd(top_dir);
|
retval = osnoise_create_cpu_timerlat_fd(top_dir);
|
||||||
if (retval)
|
if (retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|||||||
Reference in New Issue
Block a user