From owner-svn-src-all@freebsd.org Tue Feb 21 12:43:06 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 4D386CE55D3; Tue, 21 Feb 2017 12:43:06 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id D466B13E5; Tue, 21 Feb 2017 12:43:05 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v1LCh5rj071195; Tue, 21 Feb 2017 12:43:05 GMT (envelope-from hselasky@FreeBSD.org) Received: (from hselasky@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v1LCh202071172; Tue, 21 Feb 2017 12:43:02 GMT (envelope-from hselasky@FreeBSD.org) Message-Id: <201702211243.v1LCh202071172@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: hselasky set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky Date: Tue, 21 Feb 2017 12:43:02 +0000 (UTC) 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 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 21 Feb 2017 12:43:06 -0000 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 #include #include #include 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 +#include +#include + 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 #include +#include 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 -#include #include #include 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 + #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 #include #include -#include +#include #include #include #include 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 -#include -#include -#include -#include -#include - -#include #include -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 +#include -#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 #include #include +#include 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 #include #include +#include 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 #include +#include +#include +#include + +#include + #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 *)¤t->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 #include #include +#include /* * 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 #include #include +#include #include -#include #include 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 -#include -#include #include #include 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include +#include +#include + +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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include +#include +#include + +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(¤t->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 {