Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 21 Feb 2017 12:43:02 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r314040 - in head/sys: compat/linuxkpi/common/include/linux compat/linuxkpi/common/src conf modules/linuxkpi sys
Message-ID:  <201702211243.v1LCh202071172@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Tue Feb 21 12:43:02 2017
New Revision: 314040
URL: https://svnweb.freebsd.org/changeset/base/314040

Log:
  Make the LinuxKPI task struct persistent accross system calls.
  
  A set of helper functions have been added to manage the life of the
  LinuxKPI task struct. When an external system call or task is invoked,
  a check is made to create the task struct by demand. A thread
  destructor callback is registered to free the task struct when a
  thread exits to avoid memory leaks.
  
  This change lays the ground for emulating the Linux kernel more
  closely which is a dependency by the code using the LinuxKPI APIs.
  
  Add new dedicated td_lkpi_task field has been added to struct thread
  instead of abusing td_retval[1].
  
  Fix some header file inclusions to make LINT kernel build properly
  after this change.
  
  Bump the __FreeBSD_version to force a rebuild of all kernel modules.
  
  MFC after:		1 week
  Sponsored by:		Mellanox Technologies

Added:
  head/sys/compat/linuxkpi/common/src/linux_current.c   (contents, props changed)
  head/sys/compat/linuxkpi/common/src/linux_kthread.c   (contents, props changed)
Modified:
  head/sys/compat/linuxkpi/common/include/linux/bitops.h
  head/sys/compat/linuxkpi/common/include/linux/compat.h
  head/sys/compat/linuxkpi/common/include/linux/file.h
  head/sys/compat/linuxkpi/common/include/linux/jiffies.h
  head/sys/compat/linuxkpi/common/include/linux/kdev_t.h
  head/sys/compat/linuxkpi/common/include/linux/kernel.h
  head/sys/compat/linuxkpi/common/include/linux/kthread.h
  head/sys/compat/linuxkpi/common/include/linux/rwlock.h
  head/sys/compat/linuxkpi/common/include/linux/rwsem.h
  head/sys/compat/linuxkpi/common/include/linux/sched.h
  head/sys/compat/linuxkpi/common/include/linux/semaphore.h
  head/sys/compat/linuxkpi/common/include/linux/spinlock.h
  head/sys/compat/linuxkpi/common/include/linux/types.h
  head/sys/compat/linuxkpi/common/include/linux/wait.h
  head/sys/compat/linuxkpi/common/src/linux_compat.c
  head/sys/compat/linuxkpi/common/src/linux_pci.c
  head/sys/conf/files
  head/sys/modules/linuxkpi/Makefile
  head/sys/sys/param.h
  head/sys/sys/proc.h

Modified: head/sys/compat/linuxkpi/common/include/linux/bitops.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/bitops.h	Tue Feb 21 12:37:59 2017	(r314039)
+++ head/sys/compat/linuxkpi/common/include/linux/bitops.h	Tue Feb 21 12:43:02 2017	(r314040)
@@ -31,6 +31,7 @@
 #ifndef	_LINUX_BITOPS_H_
 #define	_LINUX_BITOPS_H_
 
+#include <sys/param.h>
 #include <sys/types.h>
 #include <sys/systm.h>
 #include <sys/errno.h>

Modified: head/sys/compat/linuxkpi/common/include/linux/compat.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/compat.h	Tue Feb 21 12:37:59 2017	(r314039)
+++ head/sys/compat/linuxkpi/common/include/linux/compat.h	Tue Feb 21 12:43:02 2017	(r314040)
@@ -2,7 +2,7 @@
  * Copyright (c) 2010 Isilon Systems, Inc.
  * Copyright (c) 2010 iX Systems, Inc.
  * Copyright (c) 2010 Panasas, Inc.
- * Copyright (c) 2013, 2014 Mellanox Technologies, Ltd.
+ * Copyright (c) 2013-2017 Mellanox Technologies, Ltd.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,10 +31,29 @@
 #ifndef	_LINUX_COMPAT_H_
 #define	_LINUX_COMPAT_H_
 
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+
 struct thread;
 struct task_struct;
 
-void linux_set_current(struct thread *td, struct task_struct *t);
-void linux_clear_current(struct thread *td);
+extern int linux_alloc_current(struct thread *, int flags);
+extern void linux_free_current(struct task_struct *);
+
+static inline void
+linux_set_current(struct thread *td)
+{
+	if (__predict_false(td->td_lkpi_task == NULL))
+		linux_alloc_current(td, M_WAITOK);
+}
+
+static inline int
+linux_set_current_flags(struct thread *td, int flags)
+{
+	if (__predict_false(td->td_lkpi_task == NULL))
+		return (linux_alloc_current(td, flags));
+	return (0);
+}
 
 #endif	/* _LINUX_COMPAT_H_ */

Modified: head/sys/compat/linuxkpi/common/include/linux/file.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/file.h	Tue Feb 21 12:37:59 2017	(r314039)
+++ head/sys/compat/linuxkpi/common/include/linux/file.h	Tue Feb 21 12:43:02 2017	(r314040)
@@ -39,6 +39,7 @@
 #include <sys/proc.h>
 
 #include <linux/fs.h>
+#include <linux/slab.h>
 
 struct linux_file;
 

Modified: head/sys/compat/linuxkpi/common/include/linux/jiffies.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/jiffies.h	Tue Feb 21 12:37:59 2017	(r314039)
+++ head/sys/compat/linuxkpi/common/include/linux/jiffies.h	Tue Feb 21 12:43:02 2017	(r314040)
@@ -32,7 +32,6 @@
 #define	_LINUX_JIFFIES_H_
 
 #include <linux/types.h>
-#include <linux/kernel.h>
 #include <linux/time.h>
 
 #include <sys/time.h>

Modified: head/sys/compat/linuxkpi/common/include/linux/kdev_t.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/kdev_t.h	Tue Feb 21 12:37:59 2017	(r314039)
+++ head/sys/compat/linuxkpi/common/include/linux/kdev_t.h	Tue Feb 21 12:43:02 2017	(r314040)
@@ -31,6 +31,8 @@
 #ifndef	_LINUX_KDEV_T_H_
 #define	_LINUX_KDEV_T_H_
 
+#include <sys/types.h>
+
 #define MAJOR(dev)      major((dev))
 #define MINOR(dev)      minor((dev))
 #define MKDEV(ma, mi)   makedev((ma), (mi))

Modified: head/sys/compat/linuxkpi/common/include/linux/kernel.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/kernel.h	Tue Feb 21 12:37:59 2017	(r314039)
+++ head/sys/compat/linuxkpi/common/include/linux/kernel.h	Tue Feb 21 12:43:02 2017	(r314040)
@@ -45,7 +45,7 @@
 #include <linux/bitops.h>
 #include <linux/compiler.h>
 #include <linux/errno.h>
-#include <linux/kthread.h>
+#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/jiffies.h>
 #include <linux/wait.h>

Modified: head/sys/compat/linuxkpi/common/include/linux/kthread.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/kthread.h	Tue Feb 21 12:37:59 2017	(r314039)
+++ head/sys/compat/linuxkpi/common/include/linux/kthread.h	Tue Feb 21 12:43:02 2017	(r314040)
@@ -2,7 +2,7 @@
  * Copyright (c) 2010 Isilon Systems, Inc.
  * Copyright (c) 2010 iX Systems, Inc.
  * Copyright (c) 2010 Panasas, Inc.
- * Copyright (c) 2013-2016 Mellanox Technologies, Ltd.
+ * Copyright (c) 2013-2017 Mellanox Technologies, Ltd.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,74 +31,27 @@
 #ifndef	_LINUX_KTHREAD_H_
 #define	_LINUX_KTHREAD_H_
 
-#include <sys/param.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/kernel.h>
-#include <sys/kthread.h>
-#include <sys/sleepqueue.h>
-
-#include <linux/slab.h>
 #include <linux/sched.h>
 
-static inline void
-linux_kthread_fn(void *arg)
-{
-	struct task_struct *task;
-	struct thread *td = curthread;
-
-	task = arg;
-	task_struct_fill(td, task);
-	task_struct_set(td, task);
-	if (task->should_stop == 0)
-		task->task_ret = task->task_fn(task->task_data);
-	PROC_LOCK(td->td_proc);
-	task->should_stop = TASK_STOPPED;
-	wakeup(task);
-	PROC_UNLOCK(td->td_proc);
-	task_struct_set(td, NULL);
-	kthread_exit();
-}
-
-static inline struct task_struct *
-linux_kthread_create(int (*threadfn)(void *data), void *data)
-{
-	struct task_struct *task;
-
-	task = kzalloc(sizeof(*task), GFP_KERNEL);
-	task->task_fn = threadfn;
-	task->task_data = data;
-
-	return (task);
-}
+#include <sys/unistd.h>
+#include <sys/kthread.h>
 
-#define	kthread_run(fn, data, fmt, ...)					\
-({									\
-	struct task_struct *_task;					\
+#define	kthread_run(fn, data, fmt, ...)	({				\
+	struct task_struct *__task;					\
+	struct thread *__td;						\
 									\
-	_task = linux_kthread_create((fn), (data));			\
-	if (kthread_add(linux_kthread_fn, _task, NULL, &_task->task_thread,	\
-	    0, 0, fmt, ## __VA_ARGS__)) {				\
-		kfree(_task);						\
-		_task = NULL;						\
-	}								\
-	_task;								\
+	if (kthread_add(linux_kthread_fn, NULL, NULL, &__td,		\
+	    RFSTOPPED, 0, fmt, ## __VA_ARGS__))				\
+		__task = NULL;						\
+	else								\
+		__task = linux_kthread_setup_and_run(__td, fn, data);	\
+	__task;								\
 })
 
-#define	kthread_should_stop()	current->should_stop
-
-static inline int
-kthread_stop(struct task_struct *task)
-{
-
-	PROC_LOCK(task->task_thread->td_proc);
-	task->should_stop = TASK_SHOULD_STOP;
-	wake_up_process(task);
-	while (task->should_stop != TASK_STOPPED)
-		msleep(task, &task->task_thread->td_proc->p_mtx, PWAIT,
-		    "kstop", hz);
-	PROC_UNLOCK(task->task_thread->td_proc);
-	return task->task_ret;
-}
+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);
 
 #endif	/* _LINUX_KTHREAD_H_ */

Modified: head/sys/compat/linuxkpi/common/include/linux/rwlock.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/rwlock.h	Tue Feb 21 12:37:59 2017	(r314039)
+++ head/sys/compat/linuxkpi/common/include/linux/rwlock.h	Tue Feb 21 12:43:02 2017	(r314040)
@@ -34,6 +34,7 @@
 #include <sys/types.h>
 #include <sys/lock.h>
 #include <sys/rwlock.h>
+#include <sys/libkern.h>
 
 typedef struct {
 	struct rwlock rw;

Modified: head/sys/compat/linuxkpi/common/include/linux/rwsem.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/rwsem.h	Tue Feb 21 12:37:59 2017	(r314039)
+++ head/sys/compat/linuxkpi/common/include/linux/rwsem.h	Tue Feb 21 12:43:02 2017	(r314040)
@@ -34,6 +34,7 @@
 #include <sys/param.h>
 #include <sys/lock.h>
 #include <sys/sx.h>
+#include <sys/libkern.h>
 
 struct rw_semaphore {
 	struct sx sx;

Modified: head/sys/compat/linuxkpi/common/include/linux/sched.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/sched.h	Tue Feb 21 12:37:59 2017	(r314039)
+++ head/sys/compat/linuxkpi/common/include/linux/sched.h	Tue Feb 21 12:43:02 2017	(r314040)
@@ -2,7 +2,7 @@
  * Copyright (c) 2010 Isilon Systems, Inc.
  * Copyright (c) 2010 iX Systems, Inc.
  * Copyright (c) 2010 Panasas, Inc.
- * Copyright (c) 2013-2016 Mellanox Technologies, Ltd.
+ * Copyright (c) 2013-2017 Mellanox Technologies, Ltd.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -37,6 +37,12 @@
 #include <sys/sched.h>
 #include <sys/sleepqueue.h>
 
+#include <linux/types.h>
+#include <linux/completion.h>
+#include <linux/slab.h>
+
+#include <asm/atomic.h>
+
 #define	MAX_SCHEDULE_TIMEOUT	LONG_MAX
 
 #define	TASK_RUNNING		0
@@ -46,41 +52,22 @@
 #define	TASK_WAKEKILL		128
 #define	TASK_WAKING		256
 
-#define	TASK_SHOULD_STOP	1
-#define	TASK_STOPPED		2
-
-/*
- * A task_struct is only provided for threads created by kthread() and
- * file operation callbacks.
- *
- * Using these routines outside the above mentioned contexts will
- * cause panics because no task_struct is assigned and td_retval[1] is
- * overwritten by syscalls.
- */
 struct task_struct {
-	struct	thread *task_thread;
-	int	(*task_fn)(void *data);
-	void	*task_data;
+	struct thread *task_thread;
+	linux_task_fn_t *task_fn;
+	void   *task_data;
 	int	task_ret;
 	int	state;
-	int	should_stop;
+	atomic_t kthread_flags;
 	pid_t	pid;
 	const char    *comm;
-	void	*bsd_ioctl_data;
-	unsigned	bsd_ioctl_len;
+	void   *bsd_ioctl_data;
+	unsigned bsd_ioctl_len;
+	struct completion parked;
+	struct completion exited;
 };
 
-#define	current			task_struct_get(curthread)
-#define	task_struct_get(x)	((struct task_struct *)(uintptr_t)(x)->td_retval[1])
-#define	task_struct_fill(x, y) do {		\
-  	(y)->task_thread = (x);			\
-	(y)->comm = (x)->td_name;		\
-	(y)->pid = (x)->td_tid;			\
-} while (0)
-#define	task_struct_set(x, y)	(x)->td_retval[1] = (uintptr_t)(y)
-
-/* ensure the task_struct pointer fits into the td_retval[1] field */
-CTASSERT(sizeof(((struct thread *)0)->td_retval[1]) >= sizeof(uintptr_t));
+#define	current		((struct task_struct *)curthread->td_lkpi_task)
 
 #define	set_current_state(x)						\
 	atomic_store_rel_int((volatile int *)&current->state, (x))

Modified: head/sys/compat/linuxkpi/common/include/linux/semaphore.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/semaphore.h	Tue Feb 21 12:37:59 2017	(r314039)
+++ head/sys/compat/linuxkpi/common/include/linux/semaphore.h	Tue Feb 21 12:43:02 2017	(r314040)
@@ -34,6 +34,7 @@
 #include <sys/param.h>
 #include <sys/lock.h>
 #include <sys/sema.h>
+#include <sys/libkern.h>
 
 /*
  * XXX BSD semaphores are disused and slow.  They also do not provide a

Modified: head/sys/compat/linuxkpi/common/include/linux/spinlock.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/spinlock.h	Tue Feb 21 12:37:59 2017	(r314039)
+++ head/sys/compat/linuxkpi/common/include/linux/spinlock.h	Tue Feb 21 12:43:02 2017	(r314040)
@@ -35,9 +35,9 @@
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
+#include <sys/libkern.h>
 
 #include <linux/compiler.h>
-#include <linux/kernel.h>
 #include <linux/rwlock.h>
 
 typedef struct {

Modified: head/sys/compat/linuxkpi/common/include/linux/types.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/types.h	Tue Feb 21 12:37:59 2017	(r314039)
+++ head/sys/compat/linuxkpi/common/include/linux/types.h	Tue Feb 21 12:43:02 2017	(r314040)
@@ -63,4 +63,6 @@ typedef u64 phys_addr_t;
 #define	DECLARE_BITMAP(n, bits)						\
 	unsigned long n[howmany(bits, sizeof(long) * 8)]
 
+typedef int linux_task_fn_t(void *data);
+
 #endif	/* _LINUX_TYPES_H_ */

Modified: head/sys/compat/linuxkpi/common/include/linux/wait.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/wait.h	Tue Feb 21 12:37:59 2017	(r314039)
+++ head/sys/compat/linuxkpi/common/include/linux/wait.h	Tue Feb 21 12:43:02 2017	(r314040)
@@ -32,8 +32,6 @@
 #define	_LINUX_WAIT_H_
 
 #include <linux/compiler.h>
-#include <linux/spinlock.h>
-#include <linux/sched.h>
 #include <linux/list.h>
 #include <linux/jiffies.h>
 

Modified: head/sys/compat/linuxkpi/common/src/linux_compat.c
==============================================================================
--- head/sys/compat/linuxkpi/common/src/linux_compat.c	Tue Feb 21 12:37:59 2017	(r314039)
+++ head/sys/compat/linuxkpi/common/src/linux_compat.c	Tue Feb 21 12:43:02 2017	(r314040)
@@ -384,32 +384,14 @@ kobject_init_and_add(struct kobject *kob
 	return kobject_add_complete(kobj, parent);
 }
 
-void
-linux_set_current(struct thread *td, struct task_struct *t)
-{
-	memset(t, 0, sizeof(*t));
-	task_struct_fill(td, t);
-	task_struct_set(td, t);
-}
-
-void
-linux_clear_current(struct thread *td)
-{
-	task_struct_set(td, NULL);
-}
-
 static void
 linux_file_dtor(void *cdp)
 {
 	struct linux_file *filp;
-	struct task_struct t;
-	struct thread *td;
 
-	td = curthread;
+	linux_set_current(curthread);
 	filp = cdp;
-	linux_set_current(td, &t);
 	filp->f_op->release(filp->f_vnode, filp);
-	linux_clear_current(td);
 	vdrop(filp->f_vnode);
 	kfree(filp);
 }
@@ -419,7 +401,6 @@ linux_dev_open(struct cdev *dev, int ofl
 {
 	struct linux_cdev *ldev;
 	struct linux_file *filp;
-	struct task_struct t;
 	struct file *file;
 	int error;
 
@@ -433,7 +414,7 @@ linux_dev_open(struct cdev *dev, int ofl
 	filp->f_flags = file->f_flag;
 	vhold(file->f_vnode);
 	filp->f_vnode = file->f_vnode;
-	linux_set_current(td, &t);
+	linux_set_current(td);
 	if (filp->f_op->open) {
 		error = -filp->f_op->open(file->f_vnode, filp);
 		if (error) {
@@ -447,7 +428,6 @@ linux_dev_open(struct cdev *dev, int ofl
 		kfree(filp);
 	}
 done:
-	linux_clear_current(td);
 	return (error);
 }
 
@@ -538,7 +518,6 @@ linux_dev_ioctl(struct cdev *dev, u_long
 {
 	struct linux_cdev *ldev;
 	struct linux_file *filp;
-	struct task_struct t;
 	struct file *file;
 	unsigned size;
 	int error;
@@ -550,7 +529,8 @@ linux_dev_ioctl(struct cdev *dev, u_long
 	if ((error = devfs_get_cdevpriv((void **)&filp)) != 0)
 		return (error);
 	filp->f_flags = file->f_flag;
-	linux_set_current(td, &t);
+
+	linux_set_current(td);
 	size = IOCPARM_LEN(cmd);
 	/* refer to logic in sys_ioctl() */
 	if (size > 0) {
@@ -560,8 +540,8 @@ linux_dev_ioctl(struct cdev *dev, u_long
 		 * Background: Linux code expects a user-space address
 		 * while FreeBSD supplies a kernel-space address.
 		 */
-		t.bsd_ioctl_data = data;
-		t.bsd_ioctl_len = size;
+		current->bsd_ioctl_data = data;
+		current->bsd_ioctl_len = size;
 		data = (void *)LINUX_IOCTL_MIN_PTR;
 	} else {
 		/* fetch user-space pointer */
@@ -571,7 +551,10 @@ linux_dev_ioctl(struct cdev *dev, u_long
 		error = -filp->f_op->unlocked_ioctl(filp, cmd, (u_long)data);
 	else
 		error = ENOTTY;
-	linux_clear_current(td);
+	if (size > 0) {
+		current->bsd_ioctl_data = NULL;
+		current->bsd_ioctl_len = 0;
+	}
 
 	return (error);
 }
@@ -581,7 +564,6 @@ linux_dev_read(struct cdev *dev, struct 
 {
 	struct linux_cdev *ldev;
 	struct linux_file *filp;
-	struct task_struct t;
 	struct thread *td;
 	struct file *file;
 	ssize_t bytes;
@@ -598,7 +580,7 @@ linux_dev_read(struct cdev *dev, struct 
 	/* XXX no support for I/O vectors currently */
 	if (uio->uio_iovcnt != 1)
 		return (EOPNOTSUPP);
-	linux_set_current(td, &t);
+	linux_set_current(td);
 	if (filp->f_op->read) {
 		bytes = filp->f_op->read(filp, uio->uio_iov->iov_base,
 		    uio->uio_iov->iov_len, &uio->uio_offset);
@@ -611,7 +593,6 @@ linux_dev_read(struct cdev *dev, struct 
 			error = -bytes;
 	} else
 		error = ENXIO;
-	linux_clear_current(td);
 
 	return (error);
 }
@@ -621,7 +602,6 @@ linux_dev_write(struct cdev *dev, struct
 {
 	struct linux_cdev *ldev;
 	struct linux_file *filp;
-	struct task_struct t;
 	struct thread *td;
 	struct file *file;
 	ssize_t bytes;
@@ -638,7 +618,7 @@ linux_dev_write(struct cdev *dev, struct
 	/* XXX no support for I/O vectors currently */
 	if (uio->uio_iovcnt != 1)
 		return (EOPNOTSUPP);
-	linux_set_current(td, &t);
+	linux_set_current(td);
 	if (filp->f_op->write) {
 		bytes = filp->f_op->write(filp, uio->uio_iov->iov_base,
 		    uio->uio_iov->iov_len, &uio->uio_offset);
@@ -651,7 +631,6 @@ linux_dev_write(struct cdev *dev, struct
 			error = -bytes;
 	} else
 		error = ENXIO;
-	linux_clear_current(td);
 
 	return (error);
 }
@@ -661,7 +640,6 @@ linux_dev_poll(struct cdev *dev, int eve
 {
 	struct linux_cdev *ldev;
 	struct linux_file *filp;
-	struct task_struct t;
 	struct file *file;
 	int revents;
 	int error;
@@ -673,12 +651,11 @@ linux_dev_poll(struct cdev *dev, int eve
 	if ((error = devfs_get_cdevpriv((void **)&filp)) != 0)
 		return (error);
 	filp->f_flags = file->f_flag;
-	linux_set_current(td, &t);
+	linux_set_current(td);
 	if (filp->f_op->poll)
 		revents = filp->f_op->poll(filp, NULL) & events;
 	else
 		revents = 0;
-	linux_clear_current(td);
 
 	return (revents);
 }
@@ -690,7 +667,6 @@ linux_dev_mmap_single(struct cdev *dev, 
 	struct linux_cdev *ldev;
 	struct linux_file *filp;
 	struct thread *td;
-	struct task_struct t;
 	struct file *file;
 	struct vm_area_struct vma;
 	int error;
@@ -703,7 +679,7 @@ linux_dev_mmap_single(struct cdev *dev, 
 	if ((error = devfs_get_cdevpriv((void **)&filp)) != 0)
 		return (error);
 	filp->f_flags = file->f_flag;
-	linux_set_current(td, &t);
+	linux_set_current(td);
 	vma.vm_start = 0;
 	vma.vm_end = size;
 	vma.vm_pgoff = *offset / PAGE_SIZE;
@@ -735,7 +711,6 @@ linux_dev_mmap_single(struct cdev *dev, 
 	} else
 		error = ENODEV;
 done:
-	linux_clear_current(td);
 	return (error);
 }
 
@@ -756,7 +731,6 @@ linux_file_read(struct file *file, struc
     int flags, struct thread *td)
 {
 	struct linux_file *filp;
-	struct task_struct t;
 	ssize_t bytes;
 	int error;
 
@@ -766,7 +740,7 @@ linux_file_read(struct file *file, struc
 	/* XXX no support for I/O vectors currently */
 	if (uio->uio_iovcnt != 1)
 		return (EOPNOTSUPP);
-	linux_set_current(td, &t);
+	linux_set_current(td);
 	if (filp->f_op->read) {
 		bytes = filp->f_op->read(filp, uio->uio_iov->iov_base,
 		    uio->uio_iov->iov_len, &uio->uio_offset);
@@ -779,7 +753,6 @@ linux_file_read(struct file *file, struc
 			error = -bytes;
 	} else
 		error = ENXIO;
-	linux_clear_current(td);
 
 	return (error);
 }
@@ -789,17 +762,15 @@ linux_file_poll(struct file *file, int e
     struct thread *td)
 {
 	struct linux_file *filp;
-	struct task_struct t;
 	int revents;
 
 	filp = (struct linux_file *)file->f_data;
 	filp->f_flags = file->f_flag;
-	linux_set_current(td, &t);
+	linux_set_current(td);
 	if (filp->f_op->poll)
 		revents = filp->f_op->poll(filp, NULL) & events;
 	else
 		revents = 0;
-	linux_clear_current(td);
 
 	return (revents);
 }
@@ -808,14 +779,12 @@ static int
 linux_file_close(struct file *file, struct thread *td)
 {
 	struct linux_file *filp;
-	struct task_struct t;
 	int error;
 
 	filp = (struct linux_file *)file->f_data;
 	filp->f_flags = file->f_flag;
-	linux_set_current(td, &t);
+	linux_set_current(td);
 	error = -filp->f_op->release(NULL, filp);
-	linux_clear_current(td);
 	funsetown(&filp->f_sigio);
 	kfree(filp);
 
@@ -827,14 +796,13 @@ linux_file_ioctl(struct file *fp, u_long
     struct thread *td)
 {
 	struct linux_file *filp;
-	struct task_struct t;
 	int error;
 
 	filp = (struct linux_file *)fp->f_data;
 	filp->f_flags = fp->f_flag;
 	error = 0;
 
-	linux_set_current(td, &t);
+	linux_set_current(td);
 	switch (cmd) {
 	case FIONBIO:
 		break;
@@ -856,7 +824,6 @@ linux_file_ioctl(struct file *fp, u_long
 		error = ENOTTY;
 		break;
 	}
-	linux_clear_current(td);
 	return (error);
 }
 

Added: head/sys/compat/linuxkpi/common/src/linux_current.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/compat/linuxkpi/common/src/linux_current.c	Tue Feb 21 12:43:02 2017	(r314040)
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 2017 Hans Petter Selasky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <linux/compat.h>
+#include <linux/mm.h>
+#include <linux/kthread.h>
+
+#include <sys/kernel.h>
+#include <sys/eventhandler.h>
+#include <sys/malloc.h>
+
+static eventhandler_tag linuxkpi_thread_dtor_tag;
+
+static MALLOC_DEFINE(M_LINUX_CURRENT, "linuxcurrent", "LinuxKPI task structure");
+
+int
+linux_alloc_current(struct thread *td, int flags)
+{
+	struct task_struct *ts;
+
+	MPASS(td->td_lkpi_task == NULL);
+
+	ts = malloc(sizeof(*ts), M_LINUX_CURRENT, flags | M_ZERO);
+	if (ts == NULL)
+		return (ENOMEM);
+
+	atomic_set(&ts->kthread_flags, 0);
+	ts->task_thread = td;
+	ts->comm = td->td_name;
+	ts->pid = td->td_tid;
+	ts->state = TASK_RUNNING;
+	td->td_lkpi_task = ts;
+	return (0);
+}
+
+void
+linux_free_current(struct task_struct *ts)
+{
+	free(ts, M_LINUX_CURRENT);
+}
+
+static void
+linuxkpi_thread_dtor(void *arg __unused, struct thread *td)
+{
+	struct task_struct *ts;
+
+	ts = td->td_lkpi_task;
+	if (ts == NULL)
+		return;
+
+	td->td_lkpi_task = NULL;
+	free(ts, M_LINUX_CURRENT);
+}
+
+static void
+linux_current_init(void *arg __unused)
+{
+	linuxkpi_thread_dtor_tag = EVENTHANDLER_REGISTER(thread_dtor,
+	    linuxkpi_thread_dtor, NULL, EVENTHANDLER_PRI_ANY);
+}
+SYSINIT(linux_current, SI_SUB_EVENTHANDLER, SI_ORDER_SECOND, linux_current_init, NULL);
+
+static void
+linux_current_uninit(void *arg __unused)
+{
+	EVENTHANDLER_DEREGISTER(thread_dtor, linuxkpi_thread_dtor_tag);
+}
+SYSUNINIT(linux_current, SI_SUB_EVENTHANDLER, SI_ORDER_SECOND, linux_current_uninit, NULL);

Added: head/sys/compat/linuxkpi/common/src/linux_kthread.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/compat/linuxkpi/common/src/linux_kthread.c	Tue Feb 21 12:43:02 2017	(r314040)
@@ -0,0 +1,120 @@
+/*-
+ * Copyright (c) 2017 Hans Petter Selasky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/compat.h>
+
+#include <sys/bus.h>
+#include <sys/interrupt.h>
+#include <sys/priority.h>
+
+enum {
+	KTHREAD_SHOULD_STOP_MASK = (1 << 0),
+	KTHREAD_SHOULD_PARK_MASK = (1 << 1),
+	KTHREAD_IS_PARKED_MASK = (1 << 2),
+};
+
+bool
+kthread_should_stop_task(struct task_struct *task)
+{
+
+	return (atomic_read(&task->kthread_flags) & KTHREAD_SHOULD_STOP_MASK);
+}
+
+bool
+kthread_should_stop(void)
+{
+
+	return (atomic_read(&current->kthread_flags) & KTHREAD_SHOULD_STOP_MASK);
+}
+
+int
+kthread_stop(struct task_struct *task)	
+{
+	int retval;
+
+	/*
+	 * Assume task is still alive else caller should not call
+	 * kthread_stop():
+	 */
+	atomic_or(KTHREAD_SHOULD_STOP_MASK, &task->kthread_flags);
+	wake_up_process(task);
+	wait_for_completion(&task->exited);
+
+	/*
+	 * Get return code and free task structure:
+	 */
+	retval = task->task_ret;
+	linux_free_current(task);
+
+	return (retval);
+}
+
+struct task_struct *
+linux_kthread_setup_and_run(struct thread *td, linux_task_fn_t *task_fn, void *arg)
+{
+	struct task_struct *task;
+
+	linux_set_current(td);
+
+	task = td->td_lkpi_task;
+	task->task_fn = task_fn;
+	task->task_data = arg;
+
+	thread_lock(td);
+	/* make sure the scheduler priority is raised */
+	sched_prio(td, PI_SWI(SWI_NET));
+	/* put thread into run-queue */
+	sched_add(td, SRQ_BORING);
+	thread_unlock(td);
+
+	return (task);
+}
+
+void
+linux_kthread_fn(void *arg __unused)
+{
+	struct task_struct *task = current;
+
+	if (kthread_should_stop_task(task) == 0)
+		task->task_ret = task->task_fn(task->task_data);
+
+	if (kthread_should_stop_task(task) != 0) {
+		struct thread *td = curthread;
+
+		/* let kthread_stop() free data */
+		td->td_lkpi_task = NULL;
+
+		/* wakeup kthread_stop() */
+		complete(&task->exited);
+	}
+	kthread_exit();
+}
+

Modified: head/sys/compat/linuxkpi/common/src/linux_pci.c
==============================================================================
--- head/sys/compat/linuxkpi/common/src/linux_pci.c	Tue Feb 21 12:37:59 2017	(r314039)
+++ head/sys/compat/linuxkpi/common/src/linux_pci.c	Tue Feb 21 12:43:02 2017	(r314040)
@@ -121,12 +121,9 @@ linux_pci_attach(device_t dev)
 	struct pci_dev *pdev;
 	struct pci_driver *pdrv;
 	const struct pci_device_id *id;
-	struct task_struct t;
-	struct thread *td;
 	int error;
 
-	td = curthread;
-	linux_set_current(td, &t);
+	linux_set_current(curthread);
 	pdrv = linux_pci_find(dev, &id);
 	pdev = device_get_softc(dev);
 	pdev->dev.parent = &linux_root_device;
@@ -159,7 +156,6 @@ linux_pci_attach(device_t dev)
 		put_device(&pdev->dev);
 		error = -error;
 	}
-	linux_clear_current(td);
 	return (error);
 }
 
@@ -167,11 +163,8 @@ static int
 linux_pci_detach(device_t dev)
 {
 	struct pci_dev *pdev;
-	struct task_struct t;
-	struct thread *td;
 
-	td = curthread;
-	linux_set_current(td, &t);
+	linux_set_current(curthread);
 	pdev = device_get_softc(dev);
 	DROP_GIANT();
 	pdev->pdrv->remove(pdev);
@@ -180,7 +173,6 @@ linux_pci_detach(device_t dev)
 	list_del(&pdev->links);
 	spin_unlock(&pci_lock);
 	put_device(&pdev->dev);
-	linux_clear_current(td);
 
 	return (0);
 }
@@ -190,18 +182,14 @@ linux_pci_suspend(device_t dev)
 {
 	struct pm_message pm = { };
 	struct pci_dev *pdev;
-	struct task_struct t;
-	struct thread *td;
 	int err;
 
-	td = curthread;
-	linux_set_current(td, &t);
+	linux_set_current(curthread);
 	pdev = device_get_softc(dev);
 	if (pdev->pdrv->suspend != NULL)
 		err = -pdev->pdrv->suspend(pdev, pm);
 	else
 		err = 0;
-	linux_clear_current(td);
 	return (err);
 }
 
@@ -209,18 +197,14 @@ static int
 linux_pci_resume(device_t dev)
 {
 	struct pci_dev *pdev;
-	struct task_struct t;
-	struct thread *td;
 	int err;
 
-	td = curthread;
-	linux_set_current(td, &t);
+	linux_set_current(curthread);
 	pdev = device_get_softc(dev);
 	if (pdev->pdrv->resume != NULL)
 		err = -pdev->pdrv->resume(pdev);
 	else
 		err = 0;
-	linux_clear_current(td);
 	return (err);
 }
 
@@ -228,18 +212,14 @@ static int
 linux_pci_shutdown(device_t dev)
 {
 	struct pci_dev *pdev;
-	struct task_struct t;
-	struct thread *td;
 
-	td = curthread;
-	linux_set_current(td, &t);
+	linux_set_current(curthread);
 	pdev = device_get_softc(dev);
 	if (pdev->pdrv->shutdown != NULL) {
 		DROP_GIANT();
 		pdev->pdrv->shutdown(pdev);
 		PICKUP_GIANT();
 	}
-	linux_clear_current(td);
 	return (0);
 }
 
@@ -251,6 +231,7 @@ pci_register_driver(struct pci_driver *p
 
 	bus = devclass_find("pci");
 
+	linux_set_current(curthread);
 	spin_lock(&pci_lock);
 	list_add(&pdrv->links, &pci_drivers);
 	spin_unlock(&pci_lock);

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Tue Feb 21 12:37:59 2017	(r314039)
+++ head/sys/conf/files	Tue Feb 21 12:43:02 2017	(r314040)
@@ -4266,6 +4266,10 @@ compat/linuxkpi/common/src/linux_kmod.c	
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_compat.c	optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
+compat/linuxkpi/common/src/linux_current.c	optional compat_linuxkpi \
+	compile-with "${LINUXKPI_C}"
+compat/linuxkpi/common/src/linux_kthread.c	optional compat_linuxkpi \
+	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_pci.c		optional compat_linuxkpi pci \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_idr.c		optional compat_linuxkpi \

Modified: head/sys/modules/linuxkpi/Makefile
==============================================================================
--- head/sys/modules/linuxkpi/Makefile	Tue Feb 21 12:37:59 2017	(r314039)
+++ head/sys/modules/linuxkpi/Makefile	Tue Feb 21 12:43:02 2017	(r314040)
@@ -4,6 +4,8 @@
 KMOD=	linuxkpi
 SRCS=	linux_kmod.c \
 	linux_compat.c \
+	linux_current.c \
+	linux_kthread.c \
 	linux_pci.c \
 	linux_radix.c \
 	linux_idr.c \

Modified: head/sys/sys/param.h
==============================================================================
--- head/sys/sys/param.h	Tue Feb 21 12:37:59 2017	(r314039)
+++ head/sys/sys/param.h	Tue Feb 21 12:43:02 2017	(r314040)
@@ -58,7 +58,7 @@
  *		in the range 5 to 9.
  */
 #undef __FreeBSD_version
-#define __FreeBSD_version 1200021	/* Master, propagated to newvers */
+#define __FreeBSD_version 1200022	/* Master, propagated to newvers */
 
 /*
  * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,

Modified: head/sys/sys/proc.h
==============================================================================
--- head/sys/sys/proc.h	Tue Feb 21 12:37:59 2017	(r314039)
+++ head/sys/sys/proc.h	Tue Feb 21 12:43:02 2017	(r314040)
@@ -339,6 +339,7 @@ struct thread {
 	void		*td_emuldata;	/* Emulator state data */
 	int		td_lastcpu;	/* (t) Last cpu we were on. */
 	int		td_oncpu;	/* (t) Which cpu we are on. */
+	void		*td_lkpi_task;	/* LinuxKPI task struct pointer */
 };
 
 struct thread0_storage {



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