Deal with early kthread termination by holding a reference to the task_struct and always running the cleanup code in stop_kthread(), rather than with hacks like osnoise_migration_pending().
This avoids a potential deadlock when a later patch switches from xchg to using a lock to protect osn->kthread updates, and also deals with any other situations where a kthread might exit early. Signed-off-by: Crystal Wood <[email protected]> --- v2: New patch. I did this in response to Sashiko pointing out a deadlock in v1 with the use of osn->lock in osnoise_migration_pending. That might no longer be an issue now that detach_lock is split out, but this is still the cleaner and more robust approach. --- kernel/trace/trace_osnoise.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/kernel/trace/trace_osnoise.c b/kernel/trace/trace_osnoise.c index 953936bd5eec..47ede1696c91 100644 --- a/kernel/trace/trace_osnoise.c +++ b/kernel/trace/trace_osnoise.c @@ -1691,17 +1691,6 @@ static inline int osnoise_migration_pending(void) * thus: taint and leave to unblock the blocked thread. */ osnoise_taint("migration requested to osnoise threads, leaving."); - - /* - * Unset this thread from the threads managed by the interface. - * The tracers are responsible for cleaning their env before - * exiting. - */ - mutex_lock(&interface_lock); - this_cpu_osn_var()->kthread = NULL; - cpumask_clear_cpu(smp_processor_id(), &kthread_cpumask); - mutex_unlock(&interface_lock); - return 1; } @@ -2001,8 +1990,8 @@ static void stop_kthread(unsigned int cpu) * by killing the thread. NOTE: this is a purpose specific file. */ kill_pid(kthread->thread_pid, SIGKILL, 1); - put_task_struct(kthread); } + put_task_struct(kthread); } else { /* if no workload, just return */ if (!test_bit(OSN_WORKLOAD, &osnoise_options)) { @@ -2059,15 +2048,17 @@ static int start_kthread(unsigned int cpu) snprintf(comm, 24, "osnoise/%d", cpu); } - kthread = kthread_run_on_cpu(main, NULL, cpu, comm); + kthread = kthread_create_on_cpu(main, NULL, cpu, comm); if (IS_ERR(kthread)) { pr_err(BANNER "could not start sampling thread\n"); return -ENOMEM; } + get_task_struct(kthread); cpu_osn_var(cpu)->kthread = kthread; cpumask_set_cpu(cpu, &kthread_cpumask); + wake_up_process(kthread); return 0; } -- 2.54.0
