Hi,

Currently, when a process is calling kthread_stop(), it sets a flag
asking the thread to stop, and enters in sleep mode, but the code
doing the stop doesn't wakeup the caller of kthread_stop().

The thread should also be unparked as else it will not seen the
KTHREAD_SHOULDSTOP flag. it follows what Linux is doing.

While here, I added some comments in the locking logic for park/unpark
and stop.

Comments or OK ?

Thanks.
-- 
Sebastien Marie

-----------------------------------------------
commit 70e71461c8598e28820f1743923cac40670f7c33
from: Sébastien Marie <sema...@online.fr>
date: Thu Oct  1 07:02:46 2020 UTC
 
 properly support kthread_stop()
 - wakeup pthread_stop() caller
 - unpark the thread if parked
 
 while here, add comments for locking logic for park/unpark/stop
 
diff ec329a4429e2542bc24dd017b8001b22df43564c 
ce2b5031503711bbdd7a3067c76c4f18b1d8da82
blob - 2cbd0905406ccc9d89c86cee38673a4e9c3fcf42
blob + f0e5a5a1b282c071c97505556510952ee7a6282a
--- sys/dev/pci/drm/drm_linux.c
+++ sys/dev/pci/drm/drm_linux.c
@@ -206,6 +206,10 @@ kthread_func(void *arg)
 
        ret = thread->func(thread->data);
        thread->flags |= KTHREAD_STOPPED;
+
+       /* wakeup thread waiting in kthread_stop() */
+       wakeup(thread);
+
        kthread_exit(ret);
 }
 
@@ -256,7 +260,14 @@ kthread_parkme(void)
 
        while (thread->flags & KTHREAD_SHOULDPARK) {
                thread->flags |= KTHREAD_PARKED;
+
+               /* 
+                * wakeup kthread_park() caller
+                * to signal I am parked as asked.
+                */
                wakeup(thread);
+
+               /* wait for someone to kthread_unpark() me */
                tsleep_nsec(thread, PPAUSE, "parkme", INFSLP);
                thread->flags &= ~KTHREAD_PARKED;
        }
@@ -269,7 +280,13 @@ kthread_park(struct proc *p)
 
        while ((thread->flags & KTHREAD_PARKED) == 0) {
                thread->flags |= KTHREAD_SHOULDPARK;
+
                wake_up_process(thread->proc);
+
+               /*
+                * wait for thread to be parked.
+                * the asked thread should call kthread_parkme()
+                */
                tsleep_nsec(thread, PPAUSE, "park", INFSLP);
        }
 }
@@ -280,6 +297,8 @@ kthread_unpark(struct proc *p)
        struct kthread *thread = kthread_lookup(p);
 
        thread->flags &= ~KTHREAD_SHOULDPARK;
+
+       /* wakeup kthread_parkme() caller */
        wakeup(thread);
 }
 
@@ -297,7 +316,13 @@ kthread_stop(struct proc *p)
 
        while ((thread->flags & KTHREAD_STOPPED) == 0) {
                thread->flags |= KTHREAD_SHOULDSTOP;
+
+               /* kthread_unpark() the thread if parked */
+               kthread_unpark(p);
+
                wake_up_process(thread->proc);
+               
+               /* wait for thread to stop (func() should return) */
                tsleep_nsec(thread, PPAUSE, "stop", INFSLP);
        }
        LIST_REMOVE(thread, next);


Reply via email to