Changeset View
Changeset View
Standalone View
Standalone View
sys/compat/linuxkpi/common/include/linux/kthread.h
Show All 27 Lines | |||||
* | * | ||||
* $FreeBSD$ | * $FreeBSD$ | ||||
*/ | */ | ||||
#ifndef _LINUXKPI_LINUX_KTHREAD_H_ | #ifndef _LINUXKPI_LINUX_KTHREAD_H_ | ||||
#define _LINUXKPI_LINUX_KTHREAD_H_ | #define _LINUXKPI_LINUX_KTHREAD_H_ | ||||
#include <linux/sched.h> | #include <linux/sched.h> | ||||
#include <sys/unistd.h> | #include <sys/param.h> | ||||
#include <sys/kernel.h> | |||||
#include <sys/kthread.h> | #include <sys/kthread.h> | ||||
#include <sys/malloc.h> | |||||
#include <sys/queue.h> | |||||
#include <sys/taskqueue.h> | |||||
#include <sys/unistd.h> | |||||
struct task_struct; | |||||
struct kthread_work; | |||||
typedef void (*kthread_work_func_t)(struct kthread_work *work); | |||||
struct kthread_worker { | |||||
struct task_struct *task; | |||||
struct taskqueue *tq; | |||||
}; | |||||
struct kthread_work { | |||||
struct taskqueue *tq; | |||||
struct task task; | |||||
kthread_work_func_t func; | |||||
}; | |||||
#define kthread_run(fn, data, fmt, ...) ({ \ | #define kthread_run(fn, data, fmt, ...) ({ \ | ||||
struct task_struct *__task; \ | struct task_struct *__task; \ | ||||
struct thread *__td; \ | struct thread *__td; \ | ||||
\ | \ | ||||
if (kthread_add(linux_kthread_fn, NULL, NULL, &__td, \ | if (kthread_add(linux_kthread_fn, NULL, NULL, &__td, \ | ||||
RFSTOPPED, 0, fmt, ## __VA_ARGS__)) \ | RFSTOPPED, 0, fmt, ## __VA_ARGS__)) \ | ||||
__task = NULL; \ | __task = NULL; \ | ||||
else \ | else \ | ||||
Show All 17 Lines | |||||
#define kthread_should_stop() linux_kthread_should_stop() | #define kthread_should_stop() linux_kthread_should_stop() | ||||
#define kthread_should_stop_task(task) linux_kthread_should_stop_task(task) | #define kthread_should_stop_task(task) linux_kthread_should_stop_task(task) | ||||
#define kthread_park(task) linux_kthread_park(task) | #define kthread_park(task) linux_kthread_park(task) | ||||
#define kthread_parkme() linux_kthread_parkme() | #define kthread_parkme() linux_kthread_parkme() | ||||
#define kthread_should_park() linux_kthread_should_park() | #define kthread_should_park() linux_kthread_should_park() | ||||
#define kthread_unpark(task) linux_kthread_unpark(task) | #define kthread_unpark(task) linux_kthread_unpark(task) | ||||
#define in_atomic() linux_in_atomic() | #define in_atomic() linux_in_atomic() | ||||
/* Only kthread_(create|destroy)_worker interface is allowed */ | |||||
#define kthread_init_worker(worker) \ | |||||
_Static_assert(false, "pre-4.9 worker interface is not supported"); | |||||
task_fn_t lkpi_kthread_work_fn; | |||||
task_fn_t lkpi_kthread_worker_init_fn; | |||||
#define kthread_create_worker(flags, fmt, ...) ({ \ | |||||
struct kthread_worker *__w; \ | |||||
struct task __task; \ | |||||
\ | |||||
__w = malloc(sizeof(*__w), M_KMALLOC, M_WAITOK | M_ZERO); \ | |||||
__w->tq = taskqueue_create("lkpi kthread taskq", M_WAITOK, \ | |||||
taskqueue_thread_enqueue, &__w->tq); \ | |||||
taskqueue_start_threads(&__w->tq, 1, PWAIT, fmt, ##__VA_ARGS__);\ | |||||
TASK_INIT(&__task, 0, lkpi_kthread_worker_init_fn, __w); \ | |||||
taskqueue_enqueue(__w->tq, &__task); \ | |||||
taskqueue_drain(__w->tq, &__task); \ | |||||
__w; \ | |||||
}) | |||||
static inline void | |||||
kthread_destroy_worker(struct kthread_worker *worker) | |||||
{ | |||||
taskqueue_drain_all(worker->tq); | |||||
taskqueue_free(worker->tq); | |||||
free(worker, M_KMALLOC); | |||||
} | |||||
static inline void | |||||
kthread_init_work(struct kthread_work *work, kthread_work_func_t func) | |||||
{ | |||||
work->tq = NULL; | |||||
work->func = func; | |||||
TASK_INIT(&work->task, 0, lkpi_kthread_work_fn, work); | |||||
} | |||||
static inline bool | |||||
kthread_queue_work(struct kthread_worker *worker, struct kthread_work *work) | |||||
{ | |||||
int error; | |||||
error = taskqueue_enqueue_flags(worker->tq, &work->task, | |||||
TQFLG_FAILIF_CANCELING | TQFLG_FAILIF_PENDING); | |||||
if (error == 0) | |||||
work->tq = worker->tq; | |||||
return (error == 0); | |||||
} | |||||
static inline bool | |||||
kthread_cancel_work_sync(struct kthread_work *work) | |||||
{ | |||||
u_int pending = 0; | |||||
if (work->tq != NULL && | |||||
taskqueue_cancel(work->tq, &work->task, &pending) != 0) | |||||
taskqueue_drain(work->tq, &work->task); | |||||
return (pending != 0); | |||||
} | |||||
static inline void | |||||
kthread_flush_work(struct kthread_work *work) | |||||
{ | |||||
if (work->tq != NULL) | |||||
taskqueue_drain(work->tq, &work->task); | |||||
} | |||||
static inline void | |||||
kthread_flush_worker(struct kthread_worker *worker) | |||||
{ | |||||
taskqueue_drain_all(worker->tq); | |||||
} | |||||
#endif /* _LINUXKPI_LINUX_KTHREAD_H_ */ | #endif /* _LINUXKPI_LINUX_KTHREAD_H_ */ |