Skip to content

Commit 2fac8d6

Browse files
Daniel Bristot de Oliveirarostedt
Daniel Bristot de Oliveira
authored andcommitted
tracing/osnoise: Allow multiple instances of the same tracer
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]>
1 parent ccb6754 commit 2fac8d6

File tree

1 file changed

+78
-23
lines changed

1 file changed

+78
-23
lines changed

kernel/trace/trace_osnoise.c

Lines changed: 78 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,24 @@ static bool osnoise_has_registered_instances(void)
6464
list);
6565
}
6666

67+
/*
68+
* osnoise_instance_registered - check if a tr is already registered
69+
*/
70+
static int osnoise_instance_registered(struct trace_array *tr)
71+
{
72+
struct osnoise_instance *inst;
73+
int found = 0;
74+
75+
rcu_read_lock();
76+
list_for_each_entry_rcu(inst, &osnoise_instances, list) {
77+
if (inst->tr == tr)
78+
found = 1;
79+
}
80+
rcu_read_unlock();
81+
82+
return found;
83+
}
84+
6785
/*
6886
* osnoise_register_instance - register a new trace instance
6987
*
@@ -2102,6 +2120,16 @@ static int osnoise_workload_start(void)
21022120
{
21032121
int retval;
21042122

2123+
/*
2124+
* Instances need to be registered after calling workload
2125+
* start. Hence, if there is already an instance, the
2126+
* workload was already registered. Otherwise, this
2127+
* code is on the way to register the first instance,
2128+
* and the workload will start.
2129+
*/
2130+
if (osnoise_has_registered_instances())
2131+
return 0;
2132+
21052133
osn_var_reset_all();
21062134

21072135
retval = osnoise_hook_events();
@@ -2129,6 +2157,13 @@ static int osnoise_workload_start(void)
21292157
*/
21302158
static void osnoise_workload_stop(void)
21312159
{
2160+
/*
2161+
* Instances need to be unregistered before calling
2162+
* stop. Hence, if there is a registered instance, more
2163+
* than one instance is running, and the workload will not
2164+
* yet stop. Otherwise, this code is on the way to disable
2165+
* the last instance, and the workload can stop.
2166+
*/
21322167
if (osnoise_has_registered_instances())
21332168
return;
21342169

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

2153-
if (osnoise_has_registered_instances())
2188+
/*
2189+
* If the instance is already registered, there is no need to
2190+
* register it again.
2191+
*/
2192+
if (osnoise_instance_registered(tr))
21542193
return;
21552194

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

21632202
static void osnoise_tracer_stop(struct trace_array *tr)
21642203
{
2165-
if (!osnoise_has_registered_instances())
2166-
return;
2167-
21682204
osnoise_unregister_instance(tr);
21692205
osnoise_workload_stop();
21702206
}
21712207

21722208
static int osnoise_tracer_init(struct trace_array *tr)
21732209
{
2174-
2175-
/* Only allow one instance to enable this */
2176-
if (osnoise_has_registered_instances())
2210+
/*
2211+
* Only allow osnoise tracer if timerlat tracer is not running
2212+
* already.
2213+
*/
2214+
if (timerlat_enabled())
21772215
return -EBUSY;
21782216

21792217
tr->max_latency = 0;
@@ -2202,45 +2240,55 @@ static void timerlat_tracer_start(struct trace_array *tr)
22022240
{
22032241
int retval;
22042242

2205-
if (osnoise_has_registered_instances())
2243+
/*
2244+
* If the instance is already registered, there is no need to
2245+
* register it again.
2246+
*/
2247+
if (osnoise_instance_registered(tr))
22062248
return;
22072249

2208-
osnoise_data.timerlat_tracer = 1;
2209-
22102250
retval = osnoise_workload_start();
22112251
if (retval)
2212-
goto out_err;
2252+
pr_err(BANNER "Error starting timerlat tracer\n");
22132253

22142254
osnoise_register_instance(tr);
22152255

22162256
return;
2217-
out_err:
2218-
pr_err(BANNER "Error starting timerlat tracer\n");
22192257
}
22202258

22212259
static void timerlat_tracer_stop(struct trace_array *tr)
22222260
{
22232261
int cpu;
22242262

2225-
if (!osnoise_has_registered_instances())
2226-
return;
2227-
2228-
for_each_online_cpu(cpu)
2229-
per_cpu(per_cpu_osnoise_var, cpu).sampling = 0;
2263+
osnoise_unregister_instance(tr);
22302264

2231-
osnoise_tracer_stop(tr);
2265+
/*
2266+
* Instruct the threads to stop only if this is the last instance.
2267+
*/
2268+
if (!osnoise_has_registered_instances()) {
2269+
for_each_online_cpu(cpu)
2270+
per_cpu(per_cpu_osnoise_var, cpu).sampling = 0;
2271+
}
22322272

2233-
osnoise_data.timerlat_tracer = 0;
2273+
osnoise_workload_stop();
22342274
}
22352275

22362276
static int timerlat_tracer_init(struct trace_array *tr)
22372277
{
2238-
/* Only allow one instance to enable this */
2239-
if (osnoise_has_registered_instances())
2278+
/*
2279+
* Only allow timerlat tracer if osnoise tracer is not running already.
2280+
*/
2281+
if (osnoise_has_registered_instances() && !osnoise_data.timerlat_tracer)
22402282
return -EBUSY;
22412283

2242-
tr->max_latency = 0;
2284+
/*
2285+
* If this is the first instance, set timerlat_tracer to block
2286+
* osnoise tracer start.
2287+
*/
2288+
if (!osnoise_has_registered_instances())
2289+
osnoise_data.timerlat_tracer = 1;
22432290

2291+
tr->max_latency = 0;
22442292
timerlat_tracer_start(tr);
22452293

22462294
return 0;
@@ -2249,6 +2297,13 @@ static int timerlat_tracer_init(struct trace_array *tr)
22492297
static void timerlat_tracer_reset(struct trace_array *tr)
22502298
{
22512299
timerlat_tracer_stop(tr);
2300+
2301+
/*
2302+
* If this is the last instance, reset timerlat_tracer allowing
2303+
* osnoise to be started.
2304+
*/
2305+
if (!osnoise_has_registered_instances())
2306+
osnoise_data.timerlat_tracer = 0;
22522307
}
22532308

22542309
static struct tracer timerlat_tracer __read_mostly = {

0 commit comments

Comments
 (0)