Skip to content
/ linux Public
forked from torvalds/linux

Commit

Permalink
trace/osnoise: Support hotplug operations
Browse files Browse the repository at this point in the history
Enable and disable osnoise/timerlat thread during on CPU hotplug online
and offline operations respectivelly.

Link: https://lore.kernel.org/linux-doc/[email protected]/
Link: https://lkml.kernel.org/r/39f98590b3caeb3c32f09526214058efe0e9272a.1624372313.git.bristot@redhat.com

Cc: Phil Auld <[email protected]>
Cc: Sebastian Andrzej Siewior <[email protected]>
Cc: Kate Carcia <[email protected]>
Cc: Jonathan Corbet <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Alexandre Chartre <[email protected]>
Cc: Clark Willaims <[email protected]>
Cc: John Kacur <[email protected]>
Cc: Juri Lelli <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: "H. Peter Anvin" <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Suggested-by: Steven Rostedt (VMware) <[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 Jun 25, 2021
1 parent ba998f7 commit c8895e2
Showing 1 changed file with 135 additions and 30 deletions.
165 changes: 135 additions & 30 deletions kernel/trace/trace_osnoise.c
Original file line number Diff line number Diff line change
Expand Up @@ -1416,22 +1416,67 @@ static int timerlat_main(void *data)
#endif /* CONFIG_TIMERLAT_TRACER */

/*
* stop_per_cpu_kthread - stop per-cpu threads
* stop_kthread - stop a workload thread
*/
static void stop_kthread(unsigned int cpu)
{
struct task_struct *kthread;

kthread = per_cpu(per_cpu_osnoise_var, cpu).kthread;
if (kthread)
kthread_stop(kthread);
per_cpu(per_cpu_osnoise_var, cpu).kthread = NULL;
}

/*
* stop_per_cpu_kthread - Stop per-cpu threads
*
* Stop the osnoise sampling htread. Use this on unload and at system
* shutdown.
*/
static void stop_per_cpu_kthreads(void)
{
struct task_struct *kthread;
int cpu;

for_each_online_cpu(cpu) {
kthread = per_cpu(per_cpu_osnoise_var, cpu).kthread;
if (kthread)
kthread_stop(kthread);
per_cpu(per_cpu_osnoise_var, cpu).kthread = NULL;
get_online_cpus();

for_each_online_cpu(cpu)
stop_kthread(cpu);

put_online_cpus();
}

/*
* start_kthread - Start a workload tread
*/
static int start_kthread(unsigned int cpu)
{
struct task_struct *kthread;
void *main = osnoise_main;
char comm[24];

#ifdef CONFIG_TIMERLAT_TRACER
if (osnoise_data.timerlat_tracer) {
snprintf(comm, 24, "timerlat/%d", cpu);
main = timerlat_main;
} else {
snprintf(comm, 24, "osnoise/%d", cpu);
}
#else
snprintf(comm, 24, "osnoise/%d", cpu);
#endif
kthread = kthread_create_on_cpu(main, NULL, cpu, comm);

if (IS_ERR(kthread)) {
pr_err(BANNER "could not start sampling thread\n");
stop_per_cpu_kthreads();
return -ENOMEM;
}

per_cpu(per_cpu_osnoise_var, cpu).kthread = kthread;
wake_up_process(kthread);

return 0;
}

/*
Expand All @@ -1443,9 +1488,7 @@ static void stop_per_cpu_kthreads(void)
static int start_per_cpu_kthreads(struct trace_array *tr)
{
struct cpumask *current_mask = &save_cpumask;
struct task_struct *kthread;
char comm[24];
void *main = osnoise_main;
int retval;
int cpu;

get_online_cpus();
Expand All @@ -1457,37 +1500,91 @@ static int start_per_cpu_kthreads(struct trace_array *tr)
* And the CPU is online.
*/
cpumask_and(current_mask, cpu_online_mask, current_mask);
put_online_cpus();

for_each_online_cpu(cpu)
for_each_possible_cpu(cpu)
per_cpu(per_cpu_osnoise_var, cpu).kthread = NULL;

for_each_cpu(cpu, current_mask) {
#ifdef CONFIG_TIMERLAT_TRACER
if (osnoise_data.timerlat_tracer) {
snprintf(comm, 24, "timerlat/%d", cpu);
main = timerlat_main;
} else {
snprintf(comm, 24, "osnoise/%d", cpu);
}
#else
snprintf(comm, 24, "osnoise/%d", cpu);
#endif
kthread = kthread_create_on_cpu(main, NULL, cpu, comm);

if (IS_ERR(kthread)) {
pr_err(BANNER "could not start sampling thread\n");
retval = start_kthread(cpu);
if (retval) {
stop_per_cpu_kthreads();
return -ENOMEM;
return retval;
}

per_cpu(per_cpu_osnoise_var, cpu).kthread = kthread;
wake_up_process(kthread);
}

put_online_cpus();

return 0;
}

#ifdef CONFIG_HOTPLUG_CPU
static void osnoise_hotplug_workfn(struct work_struct *dummy)
{
struct trace_array *tr = osnoise_trace;
unsigned int cpu = smp_processor_id();


mutex_lock(&trace_types_lock);

if (!osnoise_busy)
goto out_unlock_trace;

mutex_lock(&interface_lock);
get_online_cpus();

if (!cpumask_test_cpu(cpu, &osnoise_cpumask))
goto out_unlock;

if (!cpumask_test_cpu(cpu, tr->tracing_cpumask))
goto out_unlock;

start_kthread(cpu);

out_unlock:
put_online_cpus();
mutex_unlock(&interface_lock);
out_unlock_trace:
mutex_unlock(&trace_types_lock);
}

static DECLARE_WORK(osnoise_hotplug_work, osnoise_hotplug_workfn);

/*
* osnoise_cpu_init - CPU hotplug online callback function
*/
static int osnoise_cpu_init(unsigned int cpu)
{
schedule_work_on(cpu, &osnoise_hotplug_work);
return 0;
}

/*
* osnoise_cpu_die - CPU hotplug offline callback function
*/
static int osnoise_cpu_die(unsigned int cpu)
{
stop_kthread(cpu);
return 0;
}

static void osnoise_init_hotplug_support(void)
{
int ret;

ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "trace/osnoise:online",
osnoise_cpu_init, osnoise_cpu_die);
if (ret < 0)
pr_warn(BANNER "Error to init cpu hotplug support\n");

return;
}
#else /* CONFIG_HOTPLUG_CPU */
static void osnoise_init_hotplug_support(void)
{
return 0;
}
#endif /* CONFIG_HOTPLUG_CPU */

/*
* osnoise_cpus_read - Read function for reading the "cpus" file
* @filp: The active open file structure
Expand Down Expand Up @@ -1583,7 +1680,14 @@ osnoise_cpus_write(struct file *filp, const char __user *ubuf, size_t count,
osnoise_tracer_stop(tr);

mutex_lock(&interface_lock);
/*
* osnoise_cpumask is read by CPU hotplug operations.
*/
get_online_cpus();

cpumask_copy(&osnoise_cpumask, osnoise_cpumask_new);

put_online_cpus();
mutex_unlock(&interface_lock);

if (running)
Expand Down Expand Up @@ -1940,6 +2044,7 @@ __init static int init_osnoise_tracer(void)
return ret;
}
#endif
osnoise_init_hotplug_support();

init_tracefs();

Expand Down

0 comments on commit c8895e2

Please sign in to comment.