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


Reply via email to