Skip to content

Commit

Permalink
tracing/osnoise: Allow multiple instances of the same tracer
Browse files Browse the repository at this point in the history
Currently, the user can start only one instance of timerlat/osnoise
tracers and the tracers cannot run in parallel.

As starting point to add more flexibility, let's allow the same tracer to
run on different trace instances. The workload will start when the first
trace_array (instance) is registered and stop when the last instance
is unregistered.

So, while this patch allows the same tracer to run in multiple
instances (e.g., two instances running osnoise), it still does not allow
instances of timerlat and osnoise in parallel (e.g., one timerlat and
osnoise). That is because the osnoise: events have different behavior
depending on which tracer is enabled (osnoise or timerlat). Enabling
the parallel usage of these two tracers is in my TODO list.

Link: https://lkml.kernel.org/r/38c8f14b613492a4f3f938d9d3bf0b063b72f0f0.1635702894.git.bristot@kernel.org

Cc: Ingo Molnar <[email protected]>
Cc: Tom Zanussi <[email protected]>
Cc: Masami Hiramatsu <[email protected]>
Cc: Juri Lelli <[email protected]>
Cc: Clark Williams <[email protected]>
Cc: John Kacur <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Sebastian Andrzej Siewior <[email protected]>
Cc: Daniel Bristot de Oliveira <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Daniel Bristot de Oliveira <[email protected]>
Signed-off-by: Steven Rostedt (VMware) <[email protected]>
  • Loading branch information
Daniel Bristot de Oliveira authored and rostedt committed Nov 1, 2021
1 parent ccb6754 commit 2fac8d6
Showing 1 changed file with 78 additions and 23 deletions.
101 changes: 78 additions & 23 deletions kernel/trace/trace_osnoise.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,24 @@ static bool osnoise_has_registered_instances(void)
list);
}

/*
* osnoise_instance_registered - check if a tr is already registered
*/
static int osnoise_instance_registered(struct trace_array *tr)
{
struct osnoise_instance *inst;
int found = 0;

rcu_read_lock();
list_for_each_entry_rcu(inst, &osnoise_instances, list) {
if (inst->tr == tr)
found = 1;
}
rcu_read_unlock();

return found;
}

/*
* osnoise_register_instance - register a new trace instance
*
Expand Down Expand Up @@ -2102,6 +2120,16 @@ static int osnoise_workload_start(void)
{
int retval;

/*
* Instances need to be registered after calling workload
* start. Hence, if there is already an instance, the
* workload was already registered. Otherwise, this
* code is on the way to register the first instance,
* and the workload will start.
*/
if (osnoise_has_registered_instances())
return 0;

osn_var_reset_all();

retval = osnoise_hook_events();
Expand Down Expand Up @@ -2129,6 +2157,13 @@ static int osnoise_workload_start(void)
*/
static void osnoise_workload_stop(void)
{
/*
* Instances need to be unregistered before calling
* stop. Hence, if there is a registered instance, more
* than one instance is running, and the workload will not
* yet stop. Otherwise, this code is on the way to disable
* the last instance, and the workload can stop.
*/
if (osnoise_has_registered_instances())
return;

Expand All @@ -2150,7 +2185,11 @@ static void osnoise_tracer_start(struct trace_array *tr)
{
int retval;

if (osnoise_has_registered_instances())
/*
* If the instance is already registered, there is no need to
* register it again.
*/
if (osnoise_instance_registered(tr))
return;

retval = osnoise_workload_start();
Expand All @@ -2162,18 +2201,17 @@ static void osnoise_tracer_start(struct trace_array *tr)

static void osnoise_tracer_stop(struct trace_array *tr)
{
if (!osnoise_has_registered_instances())
return;

osnoise_unregister_instance(tr);
osnoise_workload_stop();
}

static int osnoise_tracer_init(struct trace_array *tr)
{

/* Only allow one instance to enable this */
if (osnoise_has_registered_instances())
/*
* Only allow osnoise tracer if timerlat tracer is not running
* already.
*/
if (timerlat_enabled())
return -EBUSY;

tr->max_latency = 0;
Expand Down Expand Up @@ -2202,45 +2240,55 @@ static void timerlat_tracer_start(struct trace_array *tr)
{
int retval;

if (osnoise_has_registered_instances())
/*
* If the instance is already registered, there is no need to
* register it again.
*/
if (osnoise_instance_registered(tr))
return;

osnoise_data.timerlat_tracer = 1;

retval = osnoise_workload_start();
if (retval)
goto out_err;
pr_err(BANNER "Error starting timerlat tracer\n");

osnoise_register_instance(tr);

return;
out_err:
pr_err(BANNER "Error starting timerlat tracer\n");
}

static void timerlat_tracer_stop(struct trace_array *tr)
{
int cpu;

if (!osnoise_has_registered_instances())
return;

for_each_online_cpu(cpu)
per_cpu(per_cpu_osnoise_var, cpu).sampling = 0;
osnoise_unregister_instance(tr);

osnoise_tracer_stop(tr);
/*
* Instruct the threads to stop only if this is the last instance.
*/
if (!osnoise_has_registered_instances()) {
for_each_online_cpu(cpu)
per_cpu(per_cpu_osnoise_var, cpu).sampling = 0;
}

osnoise_data.timerlat_tracer = 0;
osnoise_workload_stop();
}

static int timerlat_tracer_init(struct trace_array *tr)
{
/* Only allow one instance to enable this */
if (osnoise_has_registered_instances())
/*
* Only allow timerlat tracer if osnoise tracer is not running already.
*/
if (osnoise_has_registered_instances() && !osnoise_data.timerlat_tracer)
return -EBUSY;

tr->max_latency = 0;
/*
* If this is the first instance, set timerlat_tracer to block
* osnoise tracer start.
*/
if (!osnoise_has_registered_instances())
osnoise_data.timerlat_tracer = 1;

tr->max_latency = 0;
timerlat_tracer_start(tr);

return 0;
Expand All @@ -2249,6 +2297,13 @@ static int timerlat_tracer_init(struct trace_array *tr)
static void timerlat_tracer_reset(struct trace_array *tr)
{
timerlat_tracer_stop(tr);

/*
* If this is the last instance, reset timerlat_tracer allowing
* osnoise to be started.
*/
if (!osnoise_has_registered_instances())
osnoise_data.timerlat_tracer = 0;
}

static struct tracer timerlat_tracer __read_mostly = {
Expand Down

0 comments on commit 2fac8d6

Please sign in to comment.