Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 18 Jun 2017 19:22:05 +0000 (UTC)
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r320078 - in head/sys/compat/linuxkpi/common: include/linux src
Message-ID:  <201706181922.v5IJM5x2007763@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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();
 }
-



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201706181922.v5IJM5x2007763>