diff options
author | hselasky <hselasky@FreeBSD.org> | 2015-12-21 12:20:02 +0000 |
---|---|---|
committer | hselasky <hselasky@FreeBSD.org> | 2015-12-21 12:20:02 +0000 |
commit | 67489f9300ba3401e5f83a509237e29d43890483 (patch) | |
tree | b881781e537e35ccf65c10d76f1744e025e5fe09 /sys/compat | |
parent | 5a4cafab408ee7fda2e62ec3fb35b2d4891bb5be (diff) | |
download | FreeBSD-src-67489f9300ba3401e5f83a509237e29d43890483.zip FreeBSD-src-67489f9300ba3401e5f83a509237e29d43890483.tar.gz |
Implement drain_workqueue() function.
MFC after: 1 week
Sponsored by: Mellanox Technologies
Diffstat (limited to 'sys/compat')
-rw-r--r-- | sys/compat/linuxkpi/common/include/linux/workqueue.h | 19 | ||||
-rw-r--r-- | sys/compat/linuxkpi/common/src/linux_compat.c | 1 |
2 files changed, 19 insertions, 1 deletions
diff --git a/sys/compat/linuxkpi/common/include/linux/workqueue.h b/sys/compat/linuxkpi/common/include/linux/workqueue.h index 5a2c14f..7eb2301 100644 --- a/sys/compat/linuxkpi/common/include/linux/workqueue.h +++ b/sys/compat/linuxkpi/common/include/linux/workqueue.h @@ -36,10 +36,13 @@ #include <linux/timer.h> #include <linux/slab.h> +#include <asm/atomic.h> + #include <sys/taskqueue.h> struct workqueue_struct { struct taskqueue *taskqueue; + atomic_t draining; }; struct work_struct { @@ -95,6 +98,9 @@ static inline int queue_work(struct workqueue_struct *wq, struct work_struct *work) { work->taskqueue = wq->taskqueue; + /* Check for draining */ + if (atomic_read(&wq->draining) != 0) + return (!work->work_task.ta_pending); /* Return opposite value to align with Linux logic */ return (!taskqueue_enqueue(wq->taskqueue, &work->work_task)); } @@ -106,7 +112,9 @@ queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *work, int pending; work->work.taskqueue = wq->taskqueue; - if (delay != 0) { + if (atomic_read(&wq->draining) != 0) { + pending = work->work.work_task.ta_pending; + } else if (delay != 0) { pending = work->work.work_task.ta_pending; callout_reset(&work->timer, delay, linux_delayed_work_fn, work); } else { @@ -124,6 +132,7 @@ schedule_delayed_work(struct delayed_work *dwork, struct workqueue_struct wq; wq.taskqueue = taskqueue_thread; + atomic_set(&wq.draining, 0); return (queue_delayed_work(&wq, dwork, delay)); } @@ -153,6 +162,14 @@ flush_taskqueue(struct taskqueue *tq) PRELE(curproc); } +static inline void +drain_workqueue(struct workqueue_struct *wq) +{ + atomic_inc(&wq->draining); + flush_taskqueue(wq->taskqueue); + atomic_dec(&wq->draining); +} + static inline int cancel_work_sync(struct work_struct *work) { diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c index a121988..cc096b0 100644 --- a/sys/compat/linuxkpi/common/src/linux_compat.c +++ b/sys/compat/linuxkpi/common/src/linux_compat.c @@ -945,6 +945,7 @@ linux_create_workqueue_common(const char *name, int cpus) wq = kmalloc(sizeof(*wq), M_WAITOK); wq->taskqueue = taskqueue_create(name, M_WAITOK, taskqueue_thread_enqueue, &wq->taskqueue); + atomic_set(&wq->draining, 0); taskqueue_start_threads(&wq->taskqueue, cpus, PWAIT, "%s", name); return (wq); |