mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	tracing/osnoise: Support a list of trace_array *tr
osnoise/timerlat were built to run a single instance, and for this, a single variable is enough to store the current struct trace_array *tr with information about the tracing instance. This is done via the *osnoise_trace variable. A trace_array represents a trace instance. In preparation to support multiple instances, replace the *osnoise_trace variable with an RCU protected list of instances. The operations that refer to an instance now propagate to all elements of the list (all instances). Also, replace the osnoise_busy variable with a check if the list has elements (busy). No functional change is expected with this patch, i.e., only one instance is allowed yet. Link: https://lkml.kernel.org/r/91d006e889b9a5d1ff258fe6077f021ae3f26372.1635702894.git.bristot@kernel.org Cc: Ingo Molnar <mingo@redhat.com> Cc: Tom Zanussi <zanussi@kernel.org> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Juri Lelli <juri.lelli@redhat.com> Cc: Clark Williams <williams@redhat.com> Cc: John Kacur <jkacur@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Cc: Daniel Bristot de Oliveira <bristot@kernel.org> Cc: linux-rt-users@vger.kernel.org Cc: linux-trace-devel@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Daniel Bristot de Oliveira <bristot@kernel.org> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
This commit is contained in:
		
							parent
							
								
									2bd1bdf01f
								
							
						
					
					
						commit
						dae181349f
					
				
					 1 changed files with 192 additions and 69 deletions
				
			
		| 
						 | 
					@ -38,8 +38,6 @@
 | 
				
			||||||
#define CREATE_TRACE_POINTS
 | 
					#define CREATE_TRACE_POINTS
 | 
				
			||||||
#include <trace/events/osnoise.h>
 | 
					#include <trace/events/osnoise.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct trace_array	*osnoise_trace;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Default values.
 | 
					 * Default values.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -50,6 +48,81 @@ static struct trace_array	*osnoise_trace;
 | 
				
			||||||
#define DEFAULT_TIMERLAT_PERIOD	1000			/* 1ms */
 | 
					#define DEFAULT_TIMERLAT_PERIOD	1000			/* 1ms */
 | 
				
			||||||
#define DEFAULT_TIMERLAT_PRIO	95			/* FIFO 95 */
 | 
					#define DEFAULT_TIMERLAT_PRIO	95			/* FIFO 95 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * trace_array of the enabled osnoise/timerlat instances.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct osnoise_instance {
 | 
				
			||||||
 | 
						struct list_head	list;
 | 
				
			||||||
 | 
						struct trace_array	*tr;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					struct list_head osnoise_instances;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool osnoise_has_registered_instances(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return !!list_first_or_null_rcu(&osnoise_instances,
 | 
				
			||||||
 | 
										struct osnoise_instance,
 | 
				
			||||||
 | 
										list);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * osnoise_register_instance - register a new trace instance
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Register a trace_array *tr in the list of instances running
 | 
				
			||||||
 | 
					 * osnoise/timerlat tracers.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int osnoise_register_instance(struct trace_array *tr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct osnoise_instance *inst;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * register/unregister serialization is provided by trace's
 | 
				
			||||||
 | 
						 * trace_types_lock.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						lockdep_assert_held(&trace_types_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						inst = kmalloc(sizeof(*inst), GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!inst)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						INIT_LIST_HEAD_RCU(&inst->list);
 | 
				
			||||||
 | 
						inst->tr = tr;
 | 
				
			||||||
 | 
						list_add_tail_rcu(&inst->list, &osnoise_instances);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  osnoise_unregister_instance - unregister a registered trace instance
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Remove the trace_array *tr from the list of instances running
 | 
				
			||||||
 | 
					 * osnoise/timerlat tracers.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void osnoise_unregister_instance(struct trace_array *tr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct osnoise_instance *inst;
 | 
				
			||||||
 | 
						int found = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * register/unregister serialization is provided by trace's
 | 
				
			||||||
 | 
						 * trace_types_lock.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						lockdep_assert_held(&trace_types_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_for_each_entry_rcu(inst, &osnoise_instances, list) {
 | 
				
			||||||
 | 
							if (inst->tr == tr) {
 | 
				
			||||||
 | 
								list_del_rcu(&inst->list);
 | 
				
			||||||
 | 
								found = 1;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!found)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						synchronize_rcu();
 | 
				
			||||||
 | 
						kfree(inst);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * NMI runtime info.
 | 
					 * NMI runtime info.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -248,11 +321,6 @@ static struct osnoise_data {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Boolean variable used to inform that the tracer is currently sampling.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static bool osnoise_busy;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_PREEMPT_RT
 | 
					#ifdef CONFIG_PREEMPT_RT
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Print the osnoise header info.
 | 
					 * Print the osnoise header info.
 | 
				
			||||||
| 
						 | 
					@ -315,19 +383,24 @@ static void print_osnoise_headers(struct seq_file *s)
 | 
				
			||||||
 * osnoise_taint - report an osnoise error.
 | 
					 * osnoise_taint - report an osnoise error.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#define osnoise_taint(msg) ({							\
 | 
					#define osnoise_taint(msg) ({							\
 | 
				
			||||||
	struct trace_array *tr = osnoise_trace;					\
 | 
						struct osnoise_instance *inst;						\
 | 
				
			||||||
 | 
						struct trace_buffer *buffer;						\
 | 
				
			||||||
										\
 | 
															\
 | 
				
			||||||
	trace_array_printk_buf(tr->array_buffer.buffer, _THIS_IP_, msg);	\
 | 
						rcu_read_lock();							\
 | 
				
			||||||
 | 
						list_for_each_entry_rcu(inst, &osnoise_instances, list) {		\
 | 
				
			||||||
 | 
							buffer = inst->tr->array_buffer.buffer;				\
 | 
				
			||||||
 | 
							trace_array_printk_buf(buffer, _THIS_IP_, msg);			\
 | 
				
			||||||
 | 
						}									\
 | 
				
			||||||
 | 
						rcu_read_unlock();							\
 | 
				
			||||||
	osnoise_data.tainted = true;						\
 | 
						osnoise_data.tainted = true;						\
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Record an osnoise_sample into the tracer buffer.
 | 
					 * Record an osnoise_sample into the tracer buffer.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void trace_osnoise_sample(struct osnoise_sample *sample)
 | 
					static void
 | 
				
			||||||
 | 
					__trace_osnoise_sample(struct osnoise_sample *sample, struct trace_buffer *buffer)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct trace_array *tr = osnoise_trace;
 | 
					 | 
				
			||||||
	struct trace_buffer *buffer = tr->array_buffer.buffer;
 | 
					 | 
				
			||||||
	struct trace_event_call *call = &event_osnoise;
 | 
						struct trace_event_call *call = &event_osnoise;
 | 
				
			||||||
	struct ring_buffer_event *event;
 | 
						struct ring_buffer_event *event;
 | 
				
			||||||
	struct osnoise_entry *entry;
 | 
						struct osnoise_entry *entry;
 | 
				
			||||||
| 
						 | 
					@ -350,6 +423,22 @@ static void trace_osnoise_sample(struct osnoise_sample *sample)
 | 
				
			||||||
		trace_buffer_unlock_commit_nostack(buffer, event);
 | 
							trace_buffer_unlock_commit_nostack(buffer, event);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Record an osnoise_sample on all osnoise instances.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void trace_osnoise_sample(struct osnoise_sample *sample)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct osnoise_instance *inst;
 | 
				
			||||||
 | 
						struct trace_buffer *buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rcu_read_lock();
 | 
				
			||||||
 | 
						list_for_each_entry_rcu(inst, &osnoise_instances, list) {
 | 
				
			||||||
 | 
							buffer = inst->tr->array_buffer.buffer;
 | 
				
			||||||
 | 
							__trace_osnoise_sample(sample, buffer);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						rcu_read_unlock();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_TIMERLAT_TRACER
 | 
					#ifdef CONFIG_TIMERLAT_TRACER
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Print the timerlat header info.
 | 
					 * Print the timerlat header info.
 | 
				
			||||||
| 
						 | 
					@ -388,14 +477,10 @@ static void print_timerlat_headers(struct seq_file *s)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif /* CONFIG_PREEMPT_RT */
 | 
					#endif /* CONFIG_PREEMPT_RT */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					static void
 | 
				
			||||||
 * Record an timerlat_sample into the tracer buffer.
 | 
					__trace_timerlat_sample(struct timerlat_sample *sample, struct trace_buffer *buffer)
 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void trace_timerlat_sample(struct timerlat_sample *sample)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct trace_array *tr = osnoise_trace;
 | 
					 | 
				
			||||||
	struct trace_event_call *call = &event_osnoise;
 | 
						struct trace_event_call *call = &event_osnoise;
 | 
				
			||||||
	struct trace_buffer *buffer = tr->array_buffer.buffer;
 | 
					 | 
				
			||||||
	struct ring_buffer_event *event;
 | 
						struct ring_buffer_event *event;
 | 
				
			||||||
	struct timerlat_entry *entry;
 | 
						struct timerlat_entry *entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -412,6 +497,22 @@ static void trace_timerlat_sample(struct timerlat_sample *sample)
 | 
				
			||||||
		trace_buffer_unlock_commit_nostack(buffer, event);
 | 
							trace_buffer_unlock_commit_nostack(buffer, event);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Record an timerlat_sample into the tracer buffer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void trace_timerlat_sample(struct timerlat_sample *sample)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct osnoise_instance *inst;
 | 
				
			||||||
 | 
						struct trace_buffer *buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rcu_read_lock();
 | 
				
			||||||
 | 
						list_for_each_entry_rcu(inst, &osnoise_instances, list) {
 | 
				
			||||||
 | 
							buffer = inst->tr->array_buffer.buffer;
 | 
				
			||||||
 | 
							__trace_timerlat_sample(sample, buffer);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						rcu_read_unlock();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_STACKTRACE
 | 
					#ifdef CONFIG_STACKTRACE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define	MAX_CALLS	256
 | 
					#define	MAX_CALLS	256
 | 
				
			||||||
| 
						 | 
					@ -451,29 +552,18 @@ static void timerlat_save_stack(int skip)
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
/*
 | 
					
 | 
				
			||||||
 * timerlat_dump_stack - dump a stack trace previously saved
 | 
					static void
 | 
				
			||||||
 *
 | 
					__timerlat_dump_stack(struct trace_buffer *buffer, struct trace_stack *fstack, unsigned int size)
 | 
				
			||||||
 * Dump a saved stack trace into the trace buffer.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void timerlat_dump_stack(void)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct trace_event_call *call = &event_osnoise;
 | 
						struct trace_event_call *call = &event_osnoise;
 | 
				
			||||||
	struct trace_array *tr = osnoise_trace;
 | 
					 | 
				
			||||||
	struct trace_buffer *buffer = tr->array_buffer.buffer;
 | 
					 | 
				
			||||||
	struct ring_buffer_event *event;
 | 
						struct ring_buffer_event *event;
 | 
				
			||||||
	struct trace_stack *fstack;
 | 
					 | 
				
			||||||
	struct stack_entry *entry;
 | 
						struct stack_entry *entry;
 | 
				
			||||||
	unsigned int size;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	preempt_disable_notrace();
 | 
					 | 
				
			||||||
	fstack = this_cpu_ptr(&trace_stack);
 | 
					 | 
				
			||||||
	size = fstack->stack_size;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	event = trace_buffer_lock_reserve(buffer, TRACE_STACK, sizeof(*entry) + size,
 | 
						event = trace_buffer_lock_reserve(buffer, TRACE_STACK, sizeof(*entry) + size,
 | 
				
			||||||
					  tracing_gen_ctx());
 | 
										  tracing_gen_ctx());
 | 
				
			||||||
	if (!event)
 | 
						if (!event)
 | 
				
			||||||
		goto out;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	entry = ring_buffer_event_data(event);
 | 
						entry = ring_buffer_event_data(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -482,8 +572,29 @@ static void timerlat_dump_stack(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!call_filter_check_discard(call, entry, buffer, event))
 | 
						if (!call_filter_check_discard(call, entry, buffer, event))
 | 
				
			||||||
		trace_buffer_unlock_commit_nostack(buffer, event);
 | 
							trace_buffer_unlock_commit_nostack(buffer, event);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					/*
 | 
				
			||||||
 | 
					 * timerlat_dump_stack - dump a stack trace previously saved
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void timerlat_dump_stack(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct osnoise_instance *inst;
 | 
				
			||||||
 | 
						struct trace_buffer *buffer;
 | 
				
			||||||
 | 
						struct trace_stack *fstack;
 | 
				
			||||||
 | 
						unsigned int size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						preempt_disable_notrace();
 | 
				
			||||||
 | 
						fstack = this_cpu_ptr(&trace_stack);
 | 
				
			||||||
 | 
						size = fstack->stack_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rcu_read_lock();
 | 
				
			||||||
 | 
						list_for_each_entry_rcu(inst, &osnoise_instances, list) {
 | 
				
			||||||
 | 
							buffer = inst->tr->array_buffer.buffer;
 | 
				
			||||||
 | 
							__timerlat_dump_stack(buffer, fstack, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						rcu_read_unlock();
 | 
				
			||||||
	preempt_enable_notrace();
 | 
						preempt_enable_notrace();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
| 
						 | 
					@ -1078,12 +1189,37 @@ diff_osn_sample_stats(struct osnoise_variables *osn_var, struct osnoise_sample *
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static __always_inline void osnoise_stop_tracing(void)
 | 
					static __always_inline void osnoise_stop_tracing(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct trace_array *tr = osnoise_trace;
 | 
						struct osnoise_instance *inst;
 | 
				
			||||||
 | 
						struct trace_array *tr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	trace_array_printk_buf(tr->array_buffer.buffer, _THIS_IP_,
 | 
						rcu_read_lock();
 | 
				
			||||||
			"stop tracing hit on cpu %d\n", smp_processor_id());
 | 
						list_for_each_entry_rcu(inst, &osnoise_instances, list) {
 | 
				
			||||||
 | 
							tr = inst->tr;
 | 
				
			||||||
 | 
							trace_array_printk_buf(tr->array_buffer.buffer, _THIS_IP_,
 | 
				
			||||||
 | 
									"stop tracing hit on cpu %d\n", smp_processor_id());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tracer_tracing_off(tr);
 | 
							tracer_tracing_off(tr);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						rcu_read_unlock();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * notify_new_max_latency - Notify a new max latency via fsnotify interface.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void notify_new_max_latency(u64 latency)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct osnoise_instance *inst;
 | 
				
			||||||
 | 
						struct trace_array *tr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rcu_read_lock();
 | 
				
			||||||
 | 
						list_for_each_entry_rcu(inst, &osnoise_instances, list) {
 | 
				
			||||||
 | 
							tr = inst->tr;
 | 
				
			||||||
 | 
							if (tr->max_latency < latency) {
 | 
				
			||||||
 | 
								tr->max_latency = latency;
 | 
				
			||||||
 | 
								latency_fsnotify(tr);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						rcu_read_unlock();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -1097,7 +1233,6 @@ static __always_inline void osnoise_stop_tracing(void)
 | 
				
			||||||
static int run_osnoise(void)
 | 
					static int run_osnoise(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct osnoise_variables *osn_var = this_cpu_osn_var();
 | 
						struct osnoise_variables *osn_var = this_cpu_osn_var();
 | 
				
			||||||
	struct trace_array *tr = osnoise_trace;
 | 
					 | 
				
			||||||
	u64 start, sample, last_sample;
 | 
						u64 start, sample, last_sample;
 | 
				
			||||||
	u64 last_int_count, int_count;
 | 
						u64 last_int_count, int_count;
 | 
				
			||||||
	s64 noise = 0, max_noise = 0;
 | 
						s64 noise = 0, max_noise = 0;
 | 
				
			||||||
| 
						 | 
					@ -1232,11 +1367,7 @@ static int run_osnoise(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	trace_osnoise_sample(&s);
 | 
						trace_osnoise_sample(&s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Keep a running maximum ever recorded osnoise "latency" */
 | 
						notify_new_max_latency(max_noise);
 | 
				
			||||||
	if (max_noise > tr->max_latency) {
 | 
					 | 
				
			||||||
		tr->max_latency = max_noise;
 | 
					 | 
				
			||||||
		latency_fsnotify(tr);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (osnoise_data.stop_tracing_total)
 | 
						if (osnoise_data.stop_tracing_total)
 | 
				
			||||||
		if (s.noise > osnoise_data.stop_tracing_total)
 | 
							if (s.noise > osnoise_data.stop_tracing_total)
 | 
				
			||||||
| 
						 | 
					@ -1294,7 +1425,6 @@ static int osnoise_main(void *data)
 | 
				
			||||||
static enum hrtimer_restart timerlat_irq(struct hrtimer *timer)
 | 
					static enum hrtimer_restart timerlat_irq(struct hrtimer *timer)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct osnoise_variables *osn_var = this_cpu_osn_var();
 | 
						struct osnoise_variables *osn_var = this_cpu_osn_var();
 | 
				
			||||||
	struct trace_array *tr = osnoise_trace;
 | 
					 | 
				
			||||||
	struct timerlat_variables *tlat;
 | 
						struct timerlat_variables *tlat;
 | 
				
			||||||
	struct timerlat_sample s;
 | 
						struct timerlat_sample s;
 | 
				
			||||||
	u64 now;
 | 
						u64 now;
 | 
				
			||||||
| 
						 | 
					@ -1365,11 +1495,7 @@ static enum hrtimer_restart timerlat_irq(struct hrtimer *timer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	trace_timerlat_sample(&s);
 | 
						trace_timerlat_sample(&s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Keep a running maximum ever recorded os noise "latency" */
 | 
						notify_new_max_latency(diff);
 | 
				
			||||||
	if (diff > tr->max_latency) {
 | 
					 | 
				
			||||||
		tr->max_latency = diff;
 | 
					 | 
				
			||||||
		latency_fsnotify(tr);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (osnoise_data.stop_tracing)
 | 
						if (osnoise_data.stop_tracing)
 | 
				
			||||||
		if (time_to_us(diff) >= osnoise_data.stop_tracing)
 | 
							if (time_to_us(diff) >= osnoise_data.stop_tracing)
 | 
				
			||||||
| 
						 | 
					@ -1581,7 +1707,7 @@ static void osnoise_hotplug_workfn(struct work_struct *dummy)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_lock(&trace_types_lock);
 | 
						mutex_lock(&trace_types_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!osnoise_busy)
 | 
						if (!osnoise_has_registered_instances())
 | 
				
			||||||
		goto out_unlock_trace;
 | 
							goto out_unlock_trace;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_lock(&interface_lock);
 | 
						mutex_lock(&interface_lock);
 | 
				
			||||||
| 
						 | 
					@ -1716,11 +1842,10 @@ osnoise_cpus_write(struct file *filp, const char __user *ubuf, size_t count,
 | 
				
			||||||
		goto err_free;
 | 
							goto err_free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * trace_types_lock is taken to avoid concurrency on start/stop
 | 
						 * trace_types_lock is taken to avoid concurrency on start/stop.
 | 
				
			||||||
	 * and osnoise_busy.
 | 
					 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	mutex_lock(&trace_types_lock);
 | 
						mutex_lock(&trace_types_lock);
 | 
				
			||||||
	running = osnoise_busy;
 | 
						running = osnoise_has_registered_instances();
 | 
				
			||||||
	if (running)
 | 
						if (running)
 | 
				
			||||||
		stop_per_cpu_kthreads();
 | 
							stop_per_cpu_kthreads();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1943,8 +2068,6 @@ static int osnoise_workload_start(void)
 | 
				
			||||||
		return retval;
 | 
							return retval;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	osnoise_busy = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1953,7 +2076,7 @@ static int osnoise_workload_start(void)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void osnoise_workload_stop(void)
 | 
					static void osnoise_workload_stop(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!osnoise_busy)
 | 
						if (osnoise_has_registered_instances())
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	trace_osnoise_callback_enabled = false;
 | 
						trace_osnoise_callback_enabled = false;
 | 
				
			||||||
| 
						 | 
					@ -1968,28 +2091,28 @@ static void osnoise_workload_stop(void)
 | 
				
			||||||
	unhook_irq_events();
 | 
						unhook_irq_events();
 | 
				
			||||||
	unhook_softirq_events();
 | 
						unhook_softirq_events();
 | 
				
			||||||
	unhook_thread_events();
 | 
						unhook_thread_events();
 | 
				
			||||||
 | 
					 | 
				
			||||||
	osnoise_busy = false;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void osnoise_tracer_start(struct trace_array *tr)
 | 
					static void osnoise_tracer_start(struct trace_array *tr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int retval;
 | 
						int retval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (osnoise_busy)
 | 
						if (osnoise_has_registered_instances())
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	retval = osnoise_workload_start();
 | 
						retval = osnoise_workload_start();
 | 
				
			||||||
	if (retval)
 | 
						if (retval)
 | 
				
			||||||
		pr_err(BANNER "Error starting osnoise tracer\n");
 | 
							pr_err(BANNER "Error starting osnoise tracer\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						osnoise_register_instance(tr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void osnoise_tracer_stop(struct trace_array *tr)
 | 
					static void osnoise_tracer_stop(struct trace_array *tr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!osnoise_busy)
 | 
						if (!osnoise_has_registered_instances())
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						osnoise_unregister_instance(tr);
 | 
				
			||||||
	osnoise_workload_stop();
 | 
						osnoise_workload_stop();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1997,14 +2120,12 @@ static int osnoise_tracer_init(struct trace_array *tr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Only allow one instance to enable this */
 | 
						/* Only allow one instance to enable this */
 | 
				
			||||||
	if (osnoise_busy)
 | 
						if (osnoise_has_registered_instances())
 | 
				
			||||||
		return -EBUSY;
 | 
							return -EBUSY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	osnoise_trace = tr;
 | 
					 | 
				
			||||||
	tr->max_latency = 0;
 | 
						tr->max_latency = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	osnoise_tracer_start(tr);
 | 
						osnoise_tracer_start(tr);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2028,7 +2149,7 @@ static void timerlat_tracer_start(struct trace_array *tr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int retval;
 | 
						int retval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (osnoise_busy)
 | 
						if (osnoise_has_registered_instances())
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	osnoise_data.timerlat_tracer = 1;
 | 
						osnoise_data.timerlat_tracer = 1;
 | 
				
			||||||
| 
						 | 
					@ -2037,6 +2158,8 @@ static void timerlat_tracer_start(struct trace_array *tr)
 | 
				
			||||||
	if (retval)
 | 
						if (retval)
 | 
				
			||||||
		goto out_err;
 | 
							goto out_err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						osnoise_register_instance(tr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
out_err:
 | 
					out_err:
 | 
				
			||||||
	pr_err(BANNER "Error starting timerlat tracer\n");
 | 
						pr_err(BANNER "Error starting timerlat tracer\n");
 | 
				
			||||||
| 
						 | 
					@ -2046,7 +2169,7 @@ static void timerlat_tracer_stop(struct trace_array *tr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int cpu;
 | 
						int cpu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!osnoise_busy)
 | 
						if (!osnoise_has_registered_instances())
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for_each_online_cpu(cpu)
 | 
						for_each_online_cpu(cpu)
 | 
				
			||||||
| 
						 | 
					@ -2060,11 +2183,9 @@ static void timerlat_tracer_stop(struct trace_array *tr)
 | 
				
			||||||
static int timerlat_tracer_init(struct trace_array *tr)
 | 
					static int timerlat_tracer_init(struct trace_array *tr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* Only allow one instance to enable this */
 | 
						/* Only allow one instance to enable this */
 | 
				
			||||||
	if (osnoise_busy)
 | 
						if (osnoise_has_registered_instances())
 | 
				
			||||||
		return -EBUSY;
 | 
							return -EBUSY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	osnoise_trace = tr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	tr->max_latency = 0;
 | 
						tr->max_latency = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	timerlat_tracer_start(tr);
 | 
						timerlat_tracer_start(tr);
 | 
				
			||||||
| 
						 | 
					@ -2111,6 +2232,8 @@ __init static int init_osnoise_tracer(void)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	osnoise_init_hotplug_support();
 | 
						osnoise_init_hotplug_support();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						INIT_LIST_HEAD_RCU(&osnoise_instances);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	init_tracefs();
 | 
						init_tracefs();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue