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 {
_______________________________________________
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