Author: markj
Date: Sun Jun 18 19:22:05 2017
New Revision: 320078
URL: https://svnweb.freebsd.org/changeset/base/320078

Log:
  Add kthread parking support to the LinuxKPI.
  
  Submitted by: kmacy (original version)
  Reviewed by:  hselasky
  MFC after:    1 week
  Differential Revision:        https://reviews.freebsd.org/D11264

Modified:
  head/sys/compat/linuxkpi/common/include/linux/kthread.h
  head/sys/compat/linuxkpi/common/include/linux/sched.h
  head/sys/compat/linuxkpi/common/src/linux_current.c
  head/sys/compat/linuxkpi/common/src/linux_kthread.c

Modified: head/sys/compat/linuxkpi/common/include/linux/kthread.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/kthread.h     Sun Jun 18 
18:23:39 2017        (r320077)
+++ head/sys/compat/linuxkpi/common/include/linux/kthread.h     Sun Jun 18 
19:22:05 2017        (r320078)
@@ -48,15 +48,26 @@
        __task;                                                         \
 })
 
-#define        in_atomic() ({                          \
-       linux_in_atomic();                      \
-})
+int linux_kthread_stop(struct task_struct *);
+bool linux_kthread_should_stop_task(struct task_struct *);
+bool linux_kthread_should_stop(void);
+int linux_kthread_park(struct task_struct *);
+void linux_kthread_parkme(void);
+bool linux_kthread_should_park(void);
+void linux_kthread_unpark(struct task_struct *);
+void linux_kthread_fn(void *);
+struct task_struct *linux_kthread_setup_and_run(struct thread *,
+    linux_task_fn_t *, void *arg);
+int linux_in_atomic(void);
 
-extern int kthread_stop(struct task_struct *);
-extern bool kthread_should_stop_task(struct task_struct *);
-extern bool kthread_should_stop(void);
-extern void linux_kthread_fn(void *);
-extern struct task_struct *linux_kthread_setup_and_run(struct thread *, 
linux_task_fn_t *, void *arg);
-extern int linux_in_atomic(void);
+#define        kthread_stop(task)              linux_kthread_stop(task)
+#define        kthread_should_stop()           linux_kthread_should_stop()
+#define        kthread_should_stop_task(task)  
linux_kthread_should_stop_task(task)
+#define        kthread_park(task)              linux_kthread_park(task)
+#define        kthread_parkme()                linux_kthread_parkme()
+#define        kthread_should_park()           linux_kthread_should_park()
+#define        kthread_unpark(task)            linux_kthread_unpark(task)
 
-#endif /* _LINUX_KTHREAD_H_ */
+#define        in_atomic()                     linux_in_atomic()
+
+#endif /* _LINUX_KTHREAD_H_ */

Modified: head/sys/compat/linuxkpi/common/include/linux/sched.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/sched.h       Sun Jun 18 
18:23:39 2017        (r320077)
+++ head/sys/compat/linuxkpi/common/include/linux/sched.h       Sun Jun 18 
19:22:05 2017        (r320078)
@@ -54,6 +54,7 @@
 #define        TASK_UNINTERRUPTIBLE    0x0002
 #define        TASK_NORMAL             (TASK_INTERRUPTIBLE | 
TASK_UNINTERRUPTIBLE)
 #define        TASK_WAKING             0x0100
+#define        TASK_PARKED             0x0200
 
 struct task_struct {
        struct thread *task_thread;

Modified: head/sys/compat/linuxkpi/common/src/linux_current.c
==============================================================================
--- head/sys/compat/linuxkpi/common/src/linux_current.c Sun Jun 18 18:23:39 
2017        (r320077)
+++ head/sys/compat/linuxkpi/common/src/linux_current.c Sun Jun 18 19:22:05 
2017        (r320078)
@@ -28,6 +28,7 @@
 __FBSDID("$FreeBSD$");
 
 #include <linux/compat.h>
+#include <linux/completion.h>
 #include <linux/mm.h>
 #include <linux/kthread.h>
 
@@ -68,6 +69,8 @@ linux_alloc_current(struct thread *td, int flags)
        ts->pid = td->td_tid;
        atomic_set(&ts->usage, 1);
        ts->state = TASK_RUNNING;
+       init_completion(&ts->parked);
+       init_completion(&ts->exited);
 
        proc = td->td_proc;
 

Modified: head/sys/compat/linuxkpi/common/src/linux_kthread.c
==============================================================================
--- head/sys/compat/linuxkpi/common/src/linux_kthread.c Sun Jun 18 18:23:39 
2017        (r320077)
+++ head/sys/compat/linuxkpi/common/src/linux_kthread.c Sun Jun 18 19:22:05 
2017        (r320078)
@@ -43,21 +43,21 @@ enum {
 };
 
 bool
-kthread_should_stop_task(struct task_struct *task)
+linux_kthread_should_stop_task(struct task_struct *task)
 {
 
        return (atomic_read(&task->kthread_flags) & KTHREAD_SHOULD_STOP_MASK);
 }
 
 bool
-kthread_should_stop(void)
+linux_kthread_should_stop(void)
 {
 
        return (atomic_read(&current->kthread_flags) & 
KTHREAD_SHOULD_STOP_MASK);
 }
 
 int
-kthread_stop(struct task_struct *task) 
+linux_kthread_stop(struct task_struct *task)
 {
        int retval;
 
@@ -66,6 +66,7 @@ kthread_stop(struct task_struct *task)        
         * kthread_stop():
         */
        atomic_or(KTHREAD_SHOULD_STOP_MASK, &task->kthread_flags);
+       kthread_unpark(task);
        wake_up_process(task);
        wait_for_completion(&task->exited);
 
@@ -78,6 +79,53 @@ kthread_stop(struct task_struct *task)       
        return (retval);
 }
 
+int
+linux_kthread_park(struct task_struct *task)
+{
+
+       atomic_or(KTHREAD_SHOULD_PARK_MASK, &task->kthread_flags);
+       wake_up_process(task);
+       wait_for_completion(&task->parked);
+       return (0);
+}
+
+void
+linux_kthread_parkme(void)
+{
+       struct task_struct *task;
+
+       task = current;
+       set_task_state(task, TASK_PARKED | TASK_UNINTERRUPTIBLE);
+       while (linux_kthread_should_park()) {
+               while ((atomic_fetch_or(KTHREAD_IS_PARKED_MASK,
+                   &task->kthread_flags) & KTHREAD_IS_PARKED_MASK) == 0)
+                       complete(&task->parked);
+               schedule();
+               set_task_state(task, TASK_PARKED | TASK_UNINTERRUPTIBLE);
+       }
+       atomic_andnot(KTHREAD_IS_PARKED_MASK, &task->kthread_flags);
+       set_task_state(task, TASK_RUNNING);
+}
+
+bool
+linux_kthread_should_park(void)
+{
+       struct task_struct *task;
+
+       task = current;
+       return (atomic_read(&task->kthread_flags) & KTHREAD_SHOULD_PARK_MASK);
+}
+
+void
+linux_kthread_unpark(struct task_struct *task)
+{
+
+       atomic_andnot(KTHREAD_SHOULD_PARK_MASK, &task->kthread_flags);
+       if ((atomic_fetch_andnot(KTHREAD_IS_PARKED_MASK, &task->kthread_flags) &
+           KTHREAD_IS_PARKED_MASK) != 0)
+               wake_up_state(task, TASK_PARKED);
+}
+
 struct task_struct *
 linux_kthread_setup_and_run(struct thread *td, linux_task_fn_t *task_fn, void 
*arg)
 {
@@ -104,10 +152,10 @@ linux_kthread_fn(void *arg __unused)
 {
        struct task_struct *task = current;
 
-       if (kthread_should_stop_task(task) == 0)
+       if (linux_kthread_should_stop_task(task) == 0)
                task->task_ret = task->task_fn(task->task_data);
 
-       if (kthread_should_stop_task(task) != 0) {
+       if (linux_kthread_should_stop_task(task) != 0) {
                struct thread *td = curthread;
 
                /* let kthread_stop() free data */
@@ -118,4 +166,3 @@ linux_kthread_fn(void *arg __unused)
        }
        kthread_exit();
 }
-
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to