[haiku-commits] haiku: hrev56208 - in src/libs/compat/freebsd_network: . compat/sys

  • From: waddlesplash <waddlesplash@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 21 Jun 2022 20:18:11 +0000 (UTC)

hrev56208 adds 1 changeset to branch 'master'
old head: ed20f6660f54b5c48f684ed4ad419daf2571f176
new head: 01631912293e6b193ffe904ca0e39d70761fcb5a
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=01631912293e+%5Eed20f6660f54

----------------------------------------------------------------------------

01631912293e: freebsd_network: Rework taskqueues implementation.
  
   * Use FreeBSD's queue management directly, only retaining thread
     creation and synchronization functions from Haiku.
  
   * Use FreeBSD's task structure declarations.
  
   * Use a standard non-FAST taskqueue for taskqueue_thread.
  
   * Rewrite header and adjust consumers as appropriate.

                              [ Augustin Cavalier <waddlesplash@xxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev56208
Commit:      01631912293e6b193ffe904ca0e39d70761fcb5a
URL:         https://git.haiku-os.org/haiku/commit/?id=01631912293e
Author:      Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date:        Tue Jun 21 20:17:50 2022 UTC

----------------------------------------------------------------------------

7 files changed, 786 insertions(+), 472 deletions(-)
.../compat/freebsd_iflib/compat/sys/gtaskqueue.h |   4 -
.../compat/freebsd_iflib/compat/sys/taskqueue.h  |  23 -
.../compat/freebsd_network/compat/sys/_task.h    |  72 ++-
.../freebsd_network/compat/sys/taskqueue.h       | 214 ++++++--
.../compat/freebsd_network/fbsd_subr_taskqueue.c | 519 +++++++++++++++++++
src/libs/compat/freebsd_network/taskqueue.c      | 420 ++-------------
.../compat/openbsd_network/compat/sys/task.h     |   6 +-

----------------------------------------------------------------------------

diff --git a/src/libs/compat/freebsd_iflib/compat/sys/gtaskqueue.h 
b/src/libs/compat/freebsd_iflib/compat/sys/gtaskqueue.h
index 7ef73d450b..9db06ebf9d 100644
--- a/src/libs/compat/freebsd_iflib/compat/sys/gtaskqueue.h
+++ b/src/libs/compat/freebsd_iflib/compat/sys/gtaskqueue.h
@@ -85,10 +85,6 @@ void taskqgroup_config_gtask_init(void *ctx, struct 
grouptask *gtask,
            gtask_fn_t *fn, const char *name);
 void   taskqgroup_config_gtask_deinit(struct grouptask *gtask);
 
-#define TASK_ENQUEUED                  0x1
-#define TASK_SKIP_WAKEUP               0x2
-#define TASK_NOENQUEUE                 0x4
-
 #define        GTASK_INIT(gtask, flags, priority, func, context) do {  \
        (gtask)->ta_flags = flags;                              \
        (gtask)->ta_priority = (priority);                      \
diff --git a/src/libs/compat/freebsd_iflib/compat/sys/taskqueue.h 
b/src/libs/compat/freebsd_iflib/compat/sys/taskqueue.h
deleted file mode 100644
index 728e88e152..0000000000
--- a/src/libs/compat/freebsd_iflib/compat/sys/taskqueue.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2018, Haiku Inc. All rights reserved.
- * Distributed under the terms of the MIT License.
- */
-#ifndef _FBSD_IFLIB_SYS_TASKQUEUE_H_
-#define _FBSD_IFLIB_SYS_TASKQUEUE_H_
-
-/* include the real sys/taskqueue.h */
-#include_next <sys/taskqueue.h>
-
-typedef void (*taskqueue_callback_fn)(void *context);
-
-
-enum taskqueue_callback_type {
-       TASKQUEUE_CALLBACK_TYPE_INIT,
-       TASKQUEUE_CALLBACK_TYPE_SHUTDOWN,
-};
-#define        TASKQUEUE_CALLBACK_TYPE_MIN     TASKQUEUE_CALLBACK_TYPE_INIT
-#define        TASKQUEUE_CALLBACK_TYPE_MAX     TASKQUEUE_CALLBACK_TYPE_SHUTDOWN
-#define        TASKQUEUE_NUM_CALLBACKS         TASKQUEUE_CALLBACK_TYPE_MAX + 1
-
-
-#endif /* _FBSD_IFLIB_SYS_TASKQUEUE_H_ */
diff --git a/src/libs/compat/freebsd_network/compat/sys/_task.h 
b/src/libs/compat/freebsd_network/compat/sys/_task.h
index d50ee8a88f..da8e7724d9 100644
--- a/src/libs/compat/freebsd_network/compat/sys/_task.h
+++ b/src/libs/compat/freebsd_network/compat/sys/_task.h
@@ -1,29 +1,63 @@
-/*
- * Copyright 2007 Haiku Inc. All rights reserved.
- * Distributed under the terms of the MIT License.
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2000 Doug Rabson
+ * 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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ * $FreeBSD$
  */
-#ifndef _FBSD_COMPAT_SYS__TASK_H_
-#define _FBSD_COMPAT_SYS__TASK_H_
-
 
-/* Haiku's list management */
-#include <util/list.h>
+#ifndef _SYS__TASK_H_
+#define _SYS__TASK_H_
 
+#include <sys/queue.h>
 
-typedef void (*task_fn_t)(void *context, int pending);
+/*
+ * Each task includes a function which is called from
+ * taskqueue_run().  The first argument is taken from the 'ta_context'
+ * field of struct task and the second argument is a count of how many
+ * times the task was enqueued before the call to taskqueue_run().
+ *
+ * List of locks
+ * (c) const after init
+ * (q) taskqueue lock
+ */
+typedef void task_fn_t(void *context, int pending);
 
 struct task {
-       int ta_pending;
-       int ta_priority;
-       int ta_flags;
-       task_fn_t ta_handler;
-       void *ta_argument;
-
-       struct list_link ta_link;
+       STAILQ_ENTRY(task) ta_link;     /* (q) link for queue */
+       uint16_t ta_pending;            /* (q) count times queued */
+       uint8_t ta_priority;            /* (c) Priority */
+       uint8_t ta_flags;               /* (c) Flags */
+       task_fn_t *ta_func;             /* (c) task handler */
+       void    *ta_context;            /* (c) argument for handler */
 };
 
+#define        TASK_ENQUEUED           (1<<0)
+#define        TASK_NOENQUEUE          (1<<1)
+#define TASK_SKIP_WAKEUP       (1<<2)
 
-#define TASK_NEEDSGIANT (1 << 0) /* Haiku extension, OpenBSD compatibility */
-
+#define TASK_NEEDSGIANT                (1<<3) /* Haiku extension, OpenBSD 
compatibility */
 
-#endif
+#endif /* !_SYS__TASK_H_ */
diff --git a/src/libs/compat/freebsd_network/compat/sys/taskqueue.h 
b/src/libs/compat/freebsd_network/compat/sys/taskqueue.h
index d9adb6ad87..f1009051d0 100644
--- a/src/libs/compat/freebsd_network/compat/sys/taskqueue.h
+++ b/src/libs/compat/freebsd_network/compat/sys/taskqueue.h
@@ -1,15 +1,45 @@
-/*
- * Copyright 2007-2018, Haiku, Inc. All rights reserved.
- * Distributed under the terms of the MIT License.
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * 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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ * $FreeBSD$
  */
-#ifndef _FBSD_COMPAT_SYS_TASKQUEUE_H_
-#define _FBSD_COMPAT_SYS_TASKQUEUE_H_
 
+#ifndef _SYS_TASKQUEUE_H_
+#define _SYS_TASKQUEUE_H_
+
+#ifndef _KERNEL
+#error "no user-servicable parts inside"
+#endif
 
 #include <sys/queue.h>
 #include <sys/_task.h>
-#include <sys/callout.h>
+#include <sys/_callout.h>
 
+struct taskqueue;
+struct taskqgroup;
+struct thread;
 
 struct timeout_task {
        struct taskqueue *q;
@@ -18,48 +48,148 @@ struct timeout_task {
        int    f;
 };
 
-#define        TASKQUEUE_NAMELEN               64
+enum taskqueue_callback_type {
+       TASKQUEUE_CALLBACK_TYPE_INIT,
+       TASKQUEUE_CALLBACK_TYPE_SHUTDOWN,
+};
+#define        TASKQUEUE_CALLBACK_TYPE_MIN     TASKQUEUE_CALLBACK_TYPE_INIT
+#define        TASKQUEUE_CALLBACK_TYPE_MAX     TASKQUEUE_CALLBACK_TYPE_SHUTDOWN
+#define        TASKQUEUE_NUM_CALLBACKS         TASKQUEUE_CALLBACK_TYPE_MAX + 1
+#define        TASKQUEUE_NAMELEN               32
 
-typedef void (*taskqueue_enqueue_fn)(void *context);
+typedef void (*taskqueue_callback_fn)(void *context);
 
+/*
+ * A notification callback function which is called from
+ * taskqueue_enqueue().  The context argument is given in the call to
+ * taskqueue_create().  This function would normally be used to allow the
+ * queue to arrange to run itself later (e.g., by scheduling a software
+ * interrupt or waking a kernel thread).
+ */
+typedef void (*taskqueue_enqueue_fn)(void *context);
 
-struct taskqueue;
 struct taskqueue *taskqueue_create(const char *name, int mflags,
-       taskqueue_enqueue_fn enqueue, void *context);
-int taskqueue_start_threads(struct taskqueue **tq, int count, int pri,
-       const char *name, ...) __printflike(4, 5);
-void taskqueue_free(struct taskqueue *tq);
-void taskqueue_drain(struct taskqueue *tq, struct task *task);
-void taskqueue_drain_timeout(struct taskqueue *queue,
-       struct timeout_task *timeout_task);
-void taskqueue_drain_all(struct taskqueue *tq);
-void taskqueue_block(struct taskqueue *queue);
-void taskqueue_unblock(struct taskqueue *queue);
-int taskqueue_enqueue(struct taskqueue *tq, struct task *task);
-int taskqueue_enqueue_timeout(struct taskqueue *queue,
-       struct timeout_task *ttask, int _ticks);
-int taskqueue_cancel(struct taskqueue *queue, struct task *task,
-       u_int *pendp);
-int taskqueue_cancel_timeout(struct taskqueue *queue,
-       struct timeout_task *timeout_task, u_int *pendp);
-
-void taskqueue_thread_enqueue(void *context);
-
-extern struct taskqueue *taskqueue_fast;
-extern struct taskqueue *taskqueue_swi;
-extern struct taskqueue *taskqueue_thread;
-
-int taskqueue_enqueue_fast(struct taskqueue *queue, struct task *task);
-struct taskqueue *taskqueue_create_fast(const char *name, int mflags,
-       taskqueue_enqueue_fn enqueue, void *context);
+                                       taskqueue_enqueue_fn enqueue,
+                                       void *context);
+int    taskqueue_start_threads(struct taskqueue **tqp, int count, int pri,
+                               const char *name, ...) __printflike(4, 5);
+int    taskqueue_enqueue(struct taskqueue *queue, struct task *task);
+int    taskqueue_enqueue_timeout(struct taskqueue *queue,
+               struct timeout_task *timeout_task, int _ticks);
+int    taskqueue_cancel(struct taskqueue *queue, struct task *task,
+               u_int *pendp);
+int    taskqueue_cancel_timeout(struct taskqueue *queue,
+               struct timeout_task *timeout_task, u_int *pendp);
+void   taskqueue_drain(struct taskqueue *queue, struct task *task);
+void   taskqueue_drain_timeout(struct taskqueue *queue,
+               struct timeout_task *timeout_task);
+void   taskqueue_drain_all(struct taskqueue *queue);
+void   taskqueue_free(struct taskqueue *queue);
+void   taskqueue_run(struct taskqueue *queue);
+void   taskqueue_block(struct taskqueue *queue);
+void   taskqueue_unblock(struct taskqueue *queue);
+int    taskqueue_member(struct taskqueue *queue, struct thread *td);
+void   taskqueue_set_callback(struct taskqueue *queue,
+               enum taskqueue_callback_type cb_type,
+               taskqueue_callback_fn callback, void *context);
+
+/*
+ * Functions for dedicated thread taskqueues
+ */
+void   taskqueue_thread_loop(void *arg);
+void   taskqueue_thread_enqueue(void *context);
 
-void task_init(struct task *, int prio, task_fn_t handler, void *arg);
-#define TASK_INIT(taskp, prio, hand, arg) task_init(taskp, prio, hand, arg)
+/*
+ * Initialise a task structure.
+ */
+void _task_init(struct task *, int prio, task_fn_t handler, void *arg);
+#define TASK_INIT(taskp, prio, hand, arg) _task_init(taskp, prio, hand, arg)
 #define NET_TASK_INIT TASK_INIT
 
-void timeout_task_init(struct taskqueue *queue, struct timeout_task 
*timeout_task,
-       int priority, task_fn_t func, void *context);
+void _timeout_task_init(struct taskqueue *queue,
+               struct timeout_task *timeout_task, int priority, task_fn_t func,
+               void *context);
 #define        TIMEOUT_TASK_INIT(queue, timeout_task, priority, func, context) 
\
-       timeout_task_init(queue, timeout_task, priority, func, context);
+       _timeout_task_init(queue, timeout_task, priority, func, context);
 
-#endif
+/*
+ * Declare a reference to a taskqueue.
+ */
+#define TASKQUEUE_DECLARE(name)                        \
+extern struct taskqueue *taskqueue_##name
+
+/*
+ * Define and initialise a global taskqueue that uses sleep mutexes.
+ */
+#define TASKQUEUE_DEFINE(name, enqueue, context, init)                 \
+                                                                       \
+struct taskqueue *taskqueue_##name;                                    \
+                                                                       \
+static void                                                            \
+taskqueue_define_##name(void *arg)                                     \
+{                                                                      \
+       taskqueue_##name =                                              \
+               taskqueue_create(#name, M_WAITOK, (enqueue), (context));        
\
+       init;                                                           \
+}                                                                      \
+                                                                       \
+SYSINIT(taskqueue_##name, SI_SUB_INIT_IF, SI_ORDER_SECOND,             \
+       taskqueue_define_##name, NULL);                                 \
+                                                                       \
+struct __hack
+#define TASKQUEUE_DEFINE_THREAD(name)                                  \
+TASKQUEUE_DEFINE(name, taskqueue_thread_enqueue, &taskqueue_##name,    \
+       taskqueue_start_threads(&taskqueue_##name, 1, PWAIT,            \
+       "%s taskq", #name))
+
+/*
+ * Define and initialise a global taskqueue that uses spin mutexes.
+ */
+#define TASKQUEUE_FAST_DEFINE(name, enqueue, context, init)            \
+                                                                       \
+struct taskqueue *taskqueue_##name;                                    \
+                                                                       \
+static void                                                            \
+taskqueue_define_##name(void *arg)                                     \
+{                                                                      \
+       taskqueue_##name =                                              \
+               taskqueue_create_fast(#name, M_WAITOK, (enqueue),               
\
+               (context));                                                     
\
+       init;                                                           \
+}                                                                      \
+                                                                       \
+SYSINIT(taskqueue_##name, SI_SUB_INIT_IF, SI_ORDER_SECOND,             \
+       taskqueue_define_##name, NULL);                                 \
+                                                                       \
+struct __hack
+#define TASKQUEUE_FAST_DEFINE_THREAD(name)                             \
+TASKQUEUE_FAST_DEFINE(name, taskqueue_thread_enqueue,                  \
+       &taskqueue_##name, taskqueue_start_threads(&taskqueue_##name    \
+       1, PWAIT, "%s taskq", #name))
+
+/*
+ * These queues are serviced by software interrupt handlers.  To enqueue
+ * a task, call taskqueue_enqueue(taskqueue_swi, &task) or
+ * taskqueue_enqueue(taskqueue_swi_giant, &task).
+ */
+TASKQUEUE_DECLARE(swi_giant);
+TASKQUEUE_DECLARE(swi);
+
+/*
+ * This queue is serviced by a kernel thread.  To enqueue a task, call
+ * taskqueue_enqueue(taskqueue_thread, &task).
+ */
+TASKQUEUE_DECLARE(thread);
+
+/*
+ * Queue for swi handlers dispatched from fast interrupt handlers.
+ * These are necessarily different from the above because the queue
+ * must be locked with spinlocks since sleep mutex's cannot be used
+ * from a fast interrupt handler context.
+ */
+TASKQUEUE_DECLARE(fast);
+struct taskqueue *taskqueue_create_fast(const char *name, int mflags,
+                                       taskqueue_enqueue_fn enqueue,
+                                       void *context);
+
+#endif /* !_SYS_TASKQUEUE_H_ */
diff --git a/src/libs/compat/freebsd_network/fbsd_subr_taskqueue.c 
b/src/libs/compat/freebsd_network/fbsd_subr_taskqueue.c
new file mode 100644
index 0000000000..2f237a3c64
--- /dev/null
+++ b/src/libs/compat/freebsd_network/fbsd_subr_taskqueue.c
@@ -0,0 +1,519 @@
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * 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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/libkern.h>
+#include <sys/limits.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/smp.h>
+#include <sys/taskqueue.h>
+#include <machine/stdarg.h>
+
+static MALLOC_DEFINE(M_TASKQUEUE, "taskqueue", "Task Queues");
+static void    *taskqueue_giant_ih;
+static void    *taskqueue_ih;
+
+struct taskqueue_busy {
+       struct task     *tb_running;
+       TAILQ_ENTRY(taskqueue_busy) tb_link;
+};
+
+struct task * const TB_DRAIN_WAITER = (struct task *)0x1;
+
+struct taskqueue {
+       STAILQ_HEAD(, task)     tq_queue;
+       taskqueue_enqueue_fn    tq_enqueue;
+       void                    *tq_context;
+       char                    *tq_name;
+       TAILQ_HEAD(, taskqueue_busy) tq_active;
+       struct mtx              tq_mutex;
+#ifdef __HAIKU__
+       sem_id tq_sem;
+       thread_id *tq_threads;
+       thread_id tq_thread_storage;
+       int tq_threadcount;
+#else
+       struct thread           **tq_threads;
+#endif
+       int                     tq_tcount;
+       int                     tq_spin;
+       int                     tq_flags;
+       int                     tq_callouts;
+       taskqueue_callback_fn   tq_callbacks[TASKQUEUE_NUM_CALLBACKS];
+       void                    *tq_cb_contexts[TASKQUEUE_NUM_CALLBACKS];
+};
+
+#define        TQ_FLAGS_ACTIVE         (1 << 0)
+#define        TQ_FLAGS_BLOCKED        (1 << 1)
+#define        TQ_FLAGS_UNLOCKED_ENQUEUE       (1 << 2)
+
+#define        DT_CALLOUT_ARMED        (1 << 0)
+#define        DT_DRAIN_IN_PROGRESS    (1 << 1)
+
+#define        TQ_LOCK(tq)                                                     
\
+       do {                                                            \
+               if ((tq)->tq_spin)                                      \
+                       mtx_lock_spin(&(tq)->tq_mutex);                 \
+               else                                                    \
+                       mtx_lock(&(tq)->tq_mutex);                      \
+       } while (0)
+#define        TQ_ASSERT_LOCKED(tq)    mtx_assert(&(tq)->tq_mutex, MA_OWNED)
+
+#define        TQ_UNLOCK(tq)                                                   
\
+       do {                                                            \
+               if ((tq)->tq_spin)                                      \
+                       mtx_unlock_spin(&(tq)->tq_mutex);               \
+               else                                                    \
+                       mtx_unlock(&(tq)->tq_mutex);                    \
+       } while (0)
+#define        TQ_ASSERT_UNLOCKED(tq)  mtx_assert(&(tq)->tq_mutex, MA_NOTOWNED)
+
+void
+_timeout_task_init(struct taskqueue *queue, struct timeout_task *timeout_task,
+       int priority, task_fn_t func, void *context)
+{
+
+       TASK_INIT(&timeout_task->t, priority, func, context);
+       callout_init_mtx(&timeout_task->c, &queue->tq_mutex,
+               CALLOUT_RETURNUNLOCKED);
+       timeout_task->q = queue;
+       timeout_task->f = 0;
+}
+
+static struct taskqueue *
+_taskqueue_create(const char *name, int mflags,
+                taskqueue_enqueue_fn enqueue, void *context,
+                int mtxflags, const char *mtxname __unused)
+{
+       struct taskqueue *queue;
+       char *tq_name;
+
+       tq_name = malloc(TASKQUEUE_NAMELEN, M_TASKQUEUE, mflags | M_ZERO);
+       if (tq_name == NULL)
+               return (NULL);
+
+       queue = malloc(sizeof(struct taskqueue), M_TASKQUEUE, mflags | M_ZERO);
+       if (queue == NULL) {
+               free(tq_name, M_TASKQUEUE);
+               return (NULL);
+       }
+
+       snprintf(tq_name, TASKQUEUE_NAMELEN, "%s", (name) ? name : "taskqueue");
+
+       STAILQ_INIT(&queue->tq_queue);
+       TAILQ_INIT(&queue->tq_active);
+       queue->tq_enqueue = enqueue;
+       queue->tq_context = context;
+       queue->tq_name = tq_name;
+       queue->tq_spin = (mtxflags & MTX_SPIN) != 0;
+       queue->tq_flags |= TQ_FLAGS_ACTIVE;
+       if (enqueue == taskqueue_thread_enqueue)
+               queue->tq_flags |= TQ_FLAGS_UNLOCKED_ENQUEUE;
+       mtx_init(&queue->tq_mutex, tq_name, NULL, mtxflags);
+
+       return (queue);
+}
+
+struct taskqueue *
+taskqueue_create(const char *name, int mflags,
+                taskqueue_enqueue_fn enqueue, void *context)
+{
+
+       return _taskqueue_create(name, mflags, enqueue, context,
+                       MTX_DEF, name);
+}
+
+void
+taskqueue_set_callback(struct taskqueue *queue,
+       enum taskqueue_callback_type cb_type, taskqueue_callback_fn callback,
+       void *context)
+{
+
+       KASSERT(((cb_type >= TASKQUEUE_CALLBACK_TYPE_MIN) &&
+               (cb_type <= TASKQUEUE_CALLBACK_TYPE_MAX)),
+               ("Callback type %d not valid, must be %d-%d", cb_type,
+               TASKQUEUE_CALLBACK_TYPE_MIN, TASKQUEUE_CALLBACK_TYPE_MAX));
+       KASSERT((queue->tq_callbacks[cb_type] == NULL),
+               ("Re-initialization of taskqueue callback?"));
+
+       queue->tq_callbacks[cb_type] = callback;
+       queue->tq_cb_contexts[cb_type] = context;
+}
+
+void
+taskqueue_free(struct taskqueue *queue)
+{
+
+       TQ_LOCK(queue);
+       queue->tq_flags &= ~TQ_FLAGS_ACTIVE;
+       taskqueue_terminate(queue->tq_threads, queue);
+       KASSERT(TAILQ_EMPTY(&queue->tq_active), ("Tasks still running?"));
+       KASSERT(queue->tq_callouts == 0, ("Armed timeout tasks"));
+       mtx_destroy(&queue->tq_mutex);
+       free(queue->tq_threads, M_TASKQUEUE);
+       free(queue->tq_name, M_TASKQUEUE);
+       free(queue, M_TASKQUEUE);
+}
+
+static int
+taskqueue_enqueue_locked(struct taskqueue *queue, struct task *task)
+{
+       struct task *ins;
+       struct task *prev;
+
+       KASSERT(task->ta_func != NULL, ("enqueueing task with NULL func"));
+       /*
+        * Count multiple enqueues.
+        */
+       if (task->ta_pending) {
+               if (task->ta_pending < USHRT_MAX)
+                       task->ta_pending++;
+               TQ_UNLOCK(queue);
+               return (0);
+       }
+
+       /*
+        * Optimise the case when all tasks have the same priority.
+        */
+       prev = STAILQ_LAST(&queue->tq_queue, task, ta_link);
+       if (!prev || prev->ta_priority >= task->ta_priority) {
+               STAILQ_INSERT_TAIL(&queue->tq_queue, task, ta_link);
+       } else {
+               prev = NULL;
+               for (ins = STAILQ_FIRST(&queue->tq_queue); ins;
+                        prev = ins, ins = STAILQ_NEXT(ins, ta_link))
+                       if (ins->ta_priority < task->ta_priority)
+                               break;
+
+               if (prev)
+                       STAILQ_INSERT_AFTER(&queue->tq_queue, prev, task, 
ta_link);
+               else
+                       STAILQ_INSERT_HEAD(&queue->tq_queue, task, ta_link);
+       }
+
+       task->ta_pending = 1;
+       if ((queue->tq_flags & TQ_FLAGS_UNLOCKED_ENQUEUE) != 0)
+               TQ_UNLOCK(queue);
+       if ((queue->tq_flags & TQ_FLAGS_BLOCKED) == 0)
+               queue->tq_enqueue(queue->tq_context);
+       if ((queue->tq_flags & TQ_FLAGS_UNLOCKED_ENQUEUE) == 0)
+               TQ_UNLOCK(queue);
+
+       /* Return with lock released. */
+       return (0);
+}
+
+int
+taskqueue_enqueue(struct taskqueue *queue, struct task *task)
+{
+       int res;
+
+       TQ_LOCK(queue);
+       res = taskqueue_enqueue_locked(queue, task);
+       /* The lock is released inside. */
+
+       return (res);
+}
+
+static void
+taskqueue_timeout_func(void *arg)
+{
+       struct taskqueue *queue;
+       struct timeout_task *timeout_task;
+
+       timeout_task = arg;
+       queue = timeout_task->q;
+       KASSERT((timeout_task->f & DT_CALLOUT_ARMED) != 0, ("Stray timeout"));
+       timeout_task->f &= ~DT_CALLOUT_ARMED;
+       queue->tq_callouts--;
+       taskqueue_enqueue_locked(timeout_task->q, &timeout_task->t);
+       /* The lock is released inside. */
+}
+
+int
+taskqueue_enqueue_timeout(struct taskqueue *queue,
+       struct timeout_task *timeout_task, int _ticks)
+{
+       int res;
+
+       TQ_LOCK(queue);
+       KASSERT(timeout_task->q == NULL || timeout_task->q == queue,
+               ("Migrated queue"));
+       KASSERT(!queue->tq_spin, ("Timeout for spin-queue"));
+       timeout_task->q = queue;
+       res = timeout_task->t.ta_pending;
+       if (timeout_task->f & DT_DRAIN_IN_PROGRESS) {
+               /* Do nothing */
+               TQ_UNLOCK(queue);
+               res = -1;
+       } else if (_ticks == 0) {
+               taskqueue_enqueue_locked(queue, &timeout_task->t);
+               /* The lock is released inside. */
+       } else {
+               if ((timeout_task->f & DT_CALLOUT_ARMED) != 0) {
+                       res++;
+               } else {
+                       queue->tq_callouts++;
+                       timeout_task->f |= DT_CALLOUT_ARMED;
+                       if (_ticks < 0)
+                               _ticks = -_ticks; /* Ignore overflow. */
+               }
+               if (_ticks > 0) {
+                       callout_reset(&timeout_task->c, _ticks,
+                               taskqueue_timeout_func, timeout_task);
+               }
+               TQ_UNLOCK(queue);
+       }
+       return (res);
+}
+
+static void
+taskqueue_task_nop_fn(void *context, int pending)
+{
+}
+
+void
+taskqueue_block(struct taskqueue *queue)
+{
+
+       TQ_LOCK(queue);
+       queue->tq_flags |= TQ_FLAGS_BLOCKED;
+       TQ_UNLOCK(queue);
+}
+
+void
+taskqueue_unblock(struct taskqueue *queue)
+{
+
+       TQ_LOCK(queue);
+       queue->tq_flags &= ~TQ_FLAGS_BLOCKED;
+       if (!STAILQ_EMPTY(&queue->tq_queue))
+               queue->tq_enqueue(queue->tq_context);
+       TQ_UNLOCK(queue);
+}
+
+static void
+taskqueue_run_locked(struct taskqueue *queue)
+{
+       struct taskqueue_busy tb;
+       struct taskqueue_busy *tb_first;
+       struct task *task;
+       int pending;
+
+       KASSERT(queue != NULL, ("tq is NULL"));
+       TQ_ASSERT_LOCKED(queue);
+       tb.tb_running = NULL;
+
+       while (STAILQ_FIRST(&queue->tq_queue)) {
+               TAILQ_INSERT_TAIL(&queue->tq_active, &tb, tb_link);
+
+               /*
+                * Carefully remove the first task from the queue and
+                * zero its pending count.
+                */
+               task = STAILQ_FIRST(&queue->tq_queue);
+               KASSERT(task != NULL, ("task is NULL"));
+               STAILQ_REMOVE_HEAD(&queue->tq_queue, ta_link);
+               pending = task->ta_pending;
+               task->ta_pending = 0;
+               tb.tb_running = task;
+               TQ_UNLOCK(queue);
+
+               KASSERT(task->ta_func != NULL, ("task->ta_func is NULL"));
+#ifdef __HAIKU__
+               if ((task->ta_flags & TASK_NEEDSGIANT) != 0)
+                       mtx_lock(&Giant);
+#endif
+               task->ta_func(task->ta_context, pending);
+#ifdef __HAIKU__
+               if ((task->ta_flags & TASK_NEEDSGIANT) != 0)
+                       mtx_unlock(&Giant);
+#endif
+
+               TQ_LOCK(queue);
+               tb.tb_running = NULL;
+
+               TAILQ_REMOVE(&queue->tq_active, &tb, tb_link);
+               tb_first = TAILQ_FIRST(&queue->tq_active);
+       }
+}
+
+void
+taskqueue_run(struct taskqueue *queue)
+{
+
+       TQ_LOCK(queue);
+       taskqueue_run_locked(queue);
+       TQ_UNLOCK(queue);
+}
+
+static int
+task_is_running(struct taskqueue *queue, struct task *task)
+{
+       struct taskqueue_busy *tb;
+
+       TQ_ASSERT_LOCKED(queue);
+       TAILQ_FOREACH(tb, &queue->tq_active, tb_link) {
+               if (tb->tb_running == task)
+                       return (1);
+       }
+       return (0);
+}
+
+static int
+taskqueue_cancel_locked(struct taskqueue *queue, struct task *task,
+       u_int *pendp)
+{
+
+       if (task->ta_pending > 0)
+               STAILQ_REMOVE(&queue->tq_queue, task, task, ta_link);
+       if (pendp != NULL)
+               *pendp = task->ta_pending;
+       task->ta_pending = 0;
+       return (task_is_running(queue, task) ? EBUSY : 0);
+}
+
+int
+taskqueue_cancel(struct taskqueue *queue, struct task *task, u_int *pendp)
+{
+       int error;
+
+       TQ_LOCK(queue);
+       error = taskqueue_cancel_locked(queue, task, pendp);
+       TQ_UNLOCK(queue);
+
+       return (error);
+}
+
+int
+taskqueue_cancel_timeout(struct taskqueue *queue,
+       struct timeout_task *timeout_task, u_int *pendp)
+{
+       u_int pending, pending1;
+       int error;
+
+       TQ_LOCK(queue);
+       pending = !!(callout_stop(&timeout_task->c) > 0);
+       error = taskqueue_cancel_locked(queue, &timeout_task->t, &pending1);
+       if ((timeout_task->f & DT_CALLOUT_ARMED) != 0) {
+               timeout_task->f &= ~DT_CALLOUT_ARMED;
+               queue->tq_callouts--;
+       }
+       TQ_UNLOCK(queue);
+
+       if (pendp != NULL)
+               *pendp = pending + pending1;
+       return (error);
+}
+
+void
+taskqueue_drain_timeout(struct taskqueue *queue,
+       struct timeout_task *timeout_task)
+{
+
+       /*
+        * Set flag to prevent timer from re-starting during drain:
+        */
+       TQ_LOCK(queue);
+       KASSERT((timeout_task->f & DT_DRAIN_IN_PROGRESS) == 0,
+               ("Drain already in progress"));
+       timeout_task->f |= DT_DRAIN_IN_PROGRESS;
+       TQ_UNLOCK(queue);
+
+       callout_drain(&timeout_task->c);
+       taskqueue_drain(queue, &timeout_task->t);
+
+       /*
+        * Clear flag to allow timer to re-start:
+        */
+       TQ_LOCK(queue);
+       timeout_task->f &= ~DT_DRAIN_IN_PROGRESS;
+       TQ_UNLOCK(queue);
+}
+
+int
+taskqueue_start_threads(struct taskqueue **tqp, int count, int pri,
+       const char *format, ...)
+{
+       char name[64];
+       int error;
+       va_list vl;
+
+       va_start(vl, format);
+       vsnprintf(name, sizeof(name), format, vl);
+       va_end(vl);
+
+       error = _taskqueue_start_threads(tqp, count, pri, name);
+       return (error);
+}
+
+static inline void
+taskqueue_run_callback(struct taskqueue *tq,
+       enum taskqueue_callback_type cb_type)
+{
+       taskqueue_callback_fn tq_callback;
+
+       TQ_ASSERT_UNLOCKED(tq);
+       tq_callback = tq->tq_callbacks[cb_type];
+       if (tq_callback != NULL)
+               tq_callback(tq->tq_cb_contexts[cb_type]);
+}
+
+int
+taskqueue_member(struct taskqueue *queue, struct thread *td)
+{
+       int i, j, ret = 0;
+
+       for (i = 0, j = 0; ; i++) {
+               if (queue->tq_threads[i] == NULL)
+                       continue;
+               if (queue->tq_threads[i] == td) {
+                       ret = 1;
+                       break;
+               }
+               if (++j >= queue->tq_tcount)
+                       break;
+       }
+       return (ret);
+}
+
+struct taskqueue *
+taskqueue_create_fast(const char *name, int mflags,
+                taskqueue_enqueue_fn enqueue, void *context)
+{
+       return _taskqueue_create(name, mflags, enqueue, context,
+                       MTX_SPIN, "fast_taskqueue");
+}
diff --git a/src/libs/compat/freebsd_network/taskqueue.c 
b/src/libs/compat/freebsd_network/taskqueue.c
index 7ed80a2b78..50163c576f 100644
--- a/src/libs/compat/freebsd_network/taskqueue.c
+++ b/src/libs/compat/freebsd_network/taskqueue.c
@@ -1,13 +1,8 @@
 /*
- * Copyright 2009, Colin Günther, coling@xxxxxx
- * Copyright 2007, Hugo Santos. All Rights Reserved.
+ * Copyright 2022, Haiku, Inc. All rights reserved.
  * Distributed under the terms of the MIT License.
- *
- * Authors:
- *      Hugo Santos, hugosantos@xxxxxxxxx
  */
 
-
 #include "device.h"
 
 #include <stdio.h>
@@ -17,125 +12,42 @@
 #include <compat/sys/haiku-module.h>
 
 
-#define TQ_FLAGS_ACTIVE                (1 << 0)
-#define TQ_FLAGS_BLOCKED       (1 << 1)
-#define TQ_FLAGS_PENDING       (1 << 2)
-
-#define        DT_CALLOUT_ARMED                (1 << 0)
-#define        DT_DRAIN_IN_PROGRESS    (1 << 1)
-
-struct taskqueue {
-       char tq_name[TASKQUEUE_NAMELEN];
-       struct mtx tq_mutex;
-       struct list tq_list;
-       taskqueue_enqueue_fn tq_enqueue;
-       void *tq_arg;
-       int tq_fast;
-       sem_id tq_sem;
-       thread_id *tq_threads;
-       thread_id tq_thread_storage;
-       int tq_threadcount;
-       int tq_flags;
-       int tq_callouts;
-};
-
-struct taskqueue *taskqueue_fast = NULL;
-struct taskqueue *taskqueue_swi = NULL;
-struct taskqueue *taskqueue_thread = NULL;
-
-
-static struct taskqueue *
-_taskqueue_create(const char *name, int mflags, int fast,
-       taskqueue_enqueue_fn enqueueFunction, void *context)
-{
-       struct taskqueue *tq = malloc(sizeof(struct taskqueue));
-       if (tq == NULL)
-               return NULL;
-
-       tq->tq_fast = fast;
-
-       if (fast) {
-               mtx_init(&tq->tq_mutex, name, NULL, MTX_SPIN);
-       } else {
-               mtx_init(&tq->tq_mutex, name, NULL, MTX_DEF);
-       }
+static int _taskqueue_start_threads(struct taskqueue **taskQueue,
+       int count, int priority, const char *name);
+static void taskqueue_terminate(struct thread **pp, struct taskqueue *tq);
 
-       strlcpy(tq->tq_name, name, sizeof(tq->tq_name));
-       list_init_etc(&tq->tq_list, offsetof(struct task, ta_link));
-       tq->tq_enqueue = enqueueFunction;
-       tq->tq_arg = context;
 
-       tq->tq_sem = -1;
-       tq->tq_threads = NULL;
-       tq->tq_threadcount = 0;
-       tq->tq_flags = TQ_FLAGS_ACTIVE;
-       tq->tq_callouts = 0;
-
-       return tq;
-}
+#define malloc kernel_malloc
+#define free kernel_free
+#include "fbsd_subr_taskqueue.c"
+#undef malloc
+#undef free
 
 
-static void
-tq_lock(struct taskqueue *taskQueue)
-{
-       if (taskQueue->tq_fast) {
-               mtx_lock_spin(&taskQueue->tq_mutex);
-       } else {
-               mtx_lock(&taskQueue->tq_mutex);
-       }
-}
-
-
-static void
-tq_unlock(struct taskqueue *taskQueue)
-{
-       if (taskQueue->tq_fast) {
-               mtx_unlock_spin(&taskQueue->tq_mutex);
-       } else {
-               mtx_unlock(&taskQueue->tq_mutex);
-       }
-}
-
-
-struct taskqueue *
-taskqueue_create(const char *name, int mflags,
-       taskqueue_enqueue_fn enqueueFunction, void *context)
-{
-       return _taskqueue_create(name, mflags, 0, enqueueFunction, context);
-}
+struct taskqueue *taskqueue_fast = NULL;
+struct taskqueue *taskqueue_swi = NULL;
+struct taskqueue *taskqueue_thread = NULL;
 
 
 static int32
 tq_handle_thread(void *data)
 {
        struct taskqueue *tq = data;
-       struct task *t;
-       int pending;
-       sem_id sem;
 
-       /* just a synchronization point */
-       tq_lock(tq);
-       sem = tq->tq_sem;
-       tq_unlock(tq);
-
-       while (acquire_sem(sem) == B_NO_ERROR) {
-               tq_lock(tq);
-               t = list_remove_head_item(&tq->tq_list);
-               tq_unlock(tq);
-               if (t == NULL)
-                       continue;
-               pending = t->ta_pending;
-               t->ta_pending = 0;
+       taskqueue_run_callback(tq, TASKQUEUE_CALLBACK_TYPE_INIT);
 
-               if ((t->ta_flags & TASK_NEEDSGIANT) != 0)
-                       mtx_lock(&Giant);
+       TQ_LOCK(tq);
+       sem_id sem = tq->tq_sem;
+       TQ_UNLOCK(tq);
 
-               t->ta_handler(t->ta_argument, pending);
-
-               if ((t->ta_flags & TASK_NEEDSGIANT) != 0)
-                       mtx_unlock(&Giant);
+       while (acquire_sem(sem) == B_NO_ERROR) {
+               TQ_LOCK(tq);
+               taskqueue_run_locked(tq);
+               TQ_UNLOCK(tq);
        }
 
+       taskqueue_run_callback(tq, TASKQUEUE_CALLBACK_TYPE_SHUTDOWN);
+
        return 0;
 }
 
@@ -193,56 +105,21 @@ _taskqueue_start_threads(struct taskqueue **taskQueue, 
int count, int priority,
 }
 
 
-int
-taskqueue_start_threads(struct taskqueue **taskQueue, int count, int priority,
-       const char *format, ...)
-{
-       /* we assume that start_threads is called in a sane place, and thus
-        * don't need to be locked. This is mostly due to the fact that if
-        * the TQ is 'fast', locking the TQ disables interrupts... and then
-        * we can't create semaphores, threads and bananas. */
-
-       char name[64];
-       int result;
-       va_list vl;
-
-       va_start(vl, format);
-       vsnprintf(name, sizeof(name), format, vl);
-       va_end(vl);
-
-       /*tq_lock(*tqp);*/
-       result = _taskqueue_start_threads(taskQueue, count, priority, name);
-       /*tq_unlock(*tqp);*/
-
-       return result;
-}
-
-
-void
-taskqueue_free(struct taskqueue *taskQueue)
+static void
+taskqueue_terminate(struct thread **pp, struct taskqueue *tq)
 {
-       if (taskQueue == NULL)
+       if (tq->tq_sem == -1)
                return;
 
-       /* lock and  drain list? */
-       taskQueue->tq_flags &= ~TQ_FLAGS_ACTIVE;
-       if (!taskQueue->tq_fast)
-               mtx_destroy(&taskQueue->tq_mutex);
-       if (taskQueue->tq_sem != -1) {
-               int i;
-
-               delete_sem(taskQueue->tq_sem);
-
-               for (i = 0; i < taskQueue->tq_threadcount; i++) {
-                       status_t status;
-                       wait_for_thread(taskQueue->tq_threads[i], &status);
-               }
+       delete_sem(tq->tq_sem);
 
-               if (taskQueue->tq_threadcount > 1)
-                       free(taskQueue->tq_threads);
+       for (int i = 0; i < tq->tq_threadcount; i++) {
+               status_t status;
+               wait_for_thread(tq->tq_threads[i], &status);
        }
 
-       free(taskQueue);
+       if (tq->tq_threadcount > 1)
+               free(tq->tq_threads);
 }
 
 
@@ -252,44 +129,13 @@ taskqueue_drain(struct taskqueue *taskQueue, struct task 
*task)
        if (taskQueue == NULL)
                return;
 
-       tq_lock(taskQueue);
-       while (task->ta_pending != 0) {
-               tq_unlock(taskQueue);
+       TQ_LOCK(taskQueue);
+       while (task->ta_pending != 0 || task_is_running(taskQueue, task)) {
+               TQ_UNLOCK(taskQueue);
                snooze(0);
-               tq_lock(taskQueue);
+               TQ_LOCK(taskQueue);
        }
-       tq_unlock(taskQueue);
-}
-
-
-void
-taskqueue_drain_timeout(struct taskqueue *queue,
-       struct timeout_task *timeout_task)
-{
-       /*
-        * Set flag to prevent timer from re-starting during drain:
-        */
-       tq_lock(queue);
-       KASSERT((timeout_task->f & DT_DRAIN_IN_PROGRESS) == 0,
-               ("Drain already in progress"));
-       timeout_task->f |= DT_DRAIN_IN_PROGRESS;
-       tq_unlock(queue);
-
-       callout_drain(&timeout_task->c);
-       taskqueue_drain(queue, &timeout_task->t);
-
-       /*
-        * Clear flag to allow timer to re-start:
-        */
-       tq_lock(queue);
-       timeout_task->f &= ~DT_DRAIN_IN_PROGRESS;
-       tq_unlock(queue);
-}
-
-
-static void
-taskqueue_task_nop_fn(void* context, int pending)
-{
+       TQ_UNLOCK(taskQueue);
 }
 
 
@@ -309,165 +155,6 @@ taskqueue_drain_all(struct taskqueue *taskQueue)
 }
 
 
-static void
-taskqueue_enqueue_locked(struct taskqueue *taskQueue, struct task *task)
-{
-       /* we don't really support priorities */
-       if (task->ta_pending) {
-               task->ta_pending++;
-       } else {
-               list_add_item(&taskQueue->tq_list, task);
-               task->ta_pending = 1;
-               if ((taskQueue->tq_flags & TQ_FLAGS_BLOCKED) == 0)
-                       taskQueue->tq_enqueue(taskQueue->tq_arg);
-               else
-                       taskQueue->tq_flags |= TQ_FLAGS_PENDING;
-       }
-       tq_unlock(taskQueue);
-}
-
-
-int
-taskqueue_enqueue(struct taskqueue *taskQueue, struct task *task)
-{
-       tq_lock(taskQueue);
-       taskqueue_enqueue_locked(taskQueue, task);
-       /* The lock is released inside. */
-
-       return 0;
-}
-
-
-static void
-taskqueue_timeout_func(void *arg)
-{
-       struct taskqueue *queue;
-       struct timeout_task *timeout_task;
-
-       timeout_task = arg;
-       queue = timeout_task->q;
-       KASSERT((timeout_task->f & DT_CALLOUT_ARMED) != 0,
-               ("stray timeout ('%s')", timeout_task->q->tq_name));
-       timeout_task->f &= ~DT_CALLOUT_ARMED;
-       queue->tq_callouts--;
-       taskqueue_enqueue_locked(timeout_task->q, &timeout_task->t);
-       /* The lock is released inside. */
-}
-
-
-int
-taskqueue_enqueue_timeout(struct taskqueue *queue,
-       struct timeout_task *ttask, int _ticks)
-{
-       int res;
-
-       tq_lock(queue);
-       KASSERT(ttask->q == NULL || ttask->q == queue,
-               ("Migrated queue"));
-       ttask->q = queue;
-       res = ttask->t.ta_pending;
-       if (ttask->f & DT_DRAIN_IN_PROGRESS) {
-               /* Do nothing */
-               tq_unlock(queue);
-               res = -1;
-       } else if (_ticks == 0) {
-               tq_unlock(queue);
-               taskqueue_enqueue(queue, &ttask->t);
-       } else {
-               if ((ttask->f & DT_CALLOUT_ARMED) != 0) {
-                       res++;
-               } else {
-                       queue->tq_callouts++;
-                       ttask->f |= DT_CALLOUT_ARMED;
-                       if (_ticks < 0)
-                               _ticks = -_ticks; /* Ignore overflow. */
-               }
-               tq_unlock(queue);
-               if (_ticks > 0) {
-                       callout_reset(&ttask->c, _ticks,
-                               taskqueue_timeout_func, ttask);
-               }
-       }
-       return (res);
-}
-
-
-static int
-taskqueue_cancel_locked(struct taskqueue *queue, struct task *task,
-       u_int *pendp)
-{
-       if (task->ta_pending > 0)
-               list_remove_item(&queue->tq_list, task);
-       if (pendp != NULL)
-               *pendp = task->ta_pending;
-       task->ta_pending = 0;
-       return 0;
-}
-
-
-int
-taskqueue_cancel(struct taskqueue *queue, struct task *task, u_int *pendp)
-{
-       int error;
-
-       tq_lock(queue);
-       error = taskqueue_cancel_locked(queue, task, pendp);
-       tq_unlock(queue);
-
-       return (error);
-}
-
-
-int
-taskqueue_cancel_timeout(struct taskqueue *queue,
-       struct timeout_task *timeout_task, u_int *pendp)
-{
-       u_int pending, pending1;
-       int error;
-
-       tq_lock(queue);
-       pending = !!(callout_stop(&timeout_task->c) > 0);
-       error = taskqueue_cancel_locked(queue, &timeout_task->t, &pending1);
-       if ((timeout_task->f & DT_CALLOUT_ARMED) != 0) {
-               timeout_task->f &= ~DT_CALLOUT_ARMED;
-               queue->tq_callouts--;
-       }
-       tq_unlock(queue);
-
-       if (pendp != NULL)
-               *pendp = pending + pending1;
-       return (error);
-}
-
-
-void
-taskqueue_block(struct taskqueue *taskQueue)
-{
-       if (taskQueue == NULL)
-               return;
-
-       tq_lock(taskQueue);
-       taskQueue->tq_flags |= TQ_FLAGS_BLOCKED;
-       tq_unlock(taskQueue);
-}
-
-
-void
-taskqueue_unblock(struct taskqueue *taskQueue)
-{
-       if (taskQueue == NULL)
-               return;
-
-       tq_lock(taskQueue);
-       taskQueue->tq_flags &= ~TQ_FLAGS_BLOCKED;
-       if (taskQueue->tq_flags & TQ_FLAGS_PENDING) {
-               taskQueue->tq_flags &= ~TQ_FLAGS_PENDING;
-               taskQueue->tq_enqueue(taskQueue->tq_arg);
-       }
-       tq_unlock(taskQueue);
-}
-
-
 void
 taskqueue_thread_enqueue(void *context)
 {
@@ -476,44 +163,17 @@ taskqueue_thread_enqueue(void *context)
 }
 
 
-int
-taskqueue_enqueue_fast(struct taskqueue *taskQueue, struct task *task)
-{
-       return taskqueue_enqueue(taskQueue, task);
-}
-
-
-struct taskqueue *
-taskqueue_create_fast(const char *name, int mflags,
-       taskqueue_enqueue_fn enqueueFunction, void *context)
-{
-       return _taskqueue_create(name, mflags, 1, enqueueFunction, context);
-}
-
-
 void
-task_init(struct task *task, int prio, task_fn_t handler, void *context)
+_task_init(struct task *task, int prio, task_fn_t handler, void *context)
 {
        task->ta_priority = prio;
        task->ta_flags = 0;
-       task->ta_handler = handler;
-       task->ta_argument = context;
+       task->ta_func = handler;
+       task->ta_context = context;
        task->ta_pending = 0;
 }
 
 
-void
-timeout_task_init(struct taskqueue *queue, struct timeout_task *timeout_task,
-       int priority, task_fn_t func, void *context)
-{
-       TASK_INIT(&timeout_task->t, priority, func, context);
-       callout_init_mtx(&timeout_task->c, &queue->tq_mutex,
-               CALLOUT_RETURNUNLOCKED);
-       timeout_task->q = queue;
-       timeout_task->f = 0;
-}
-
-
 status_t
 init_taskqueues()
 {
@@ -546,7 +206,7 @@ init_taskqueues()
        }
 
        if (HAIKU_DRIVER_REQUIRES(FBSD_THREAD_TASKQUEUE)) {
-               taskqueue_thread = taskqueue_create_fast("thread taskq", 0,
+               taskqueue_thread = taskqueue_create("thread taskq", 0,
                        taskqueue_thread_enqueue, &taskqueue_thread);
                if (taskqueue_thread == NULL) {
                        status = B_NO_MEMORY;
diff --git a/src/libs/compat/openbsd_network/compat/sys/task.h 
b/src/libs/compat/openbsd_network/compat/sys/task.h
index 7f14d1c11a..f4f3eb0df5 100644
--- a/src/libs/compat/openbsd_network/compat/sys/task.h
+++ b/src/libs/compat/openbsd_network/compat/sys/task.h
@@ -20,9 +20,7 @@ struct taskq {
 static void
 task_set(struct task *t, void (*fn)(void *), void *arg)
 {
-       t->ta_priority = 0;
-       t->ta_handler = fn;
-       t->ta_argument = arg;
+       TASK_INIT(t, 0, fn, arg);
 }
 
 
@@ -41,7 +39,7 @@ task_add(struct taskq* tasq, struct task *w)
                w->ta_flags |= TASK_NEEDSGIANT;
        if (task_pending(w))
                return 0;
-       return (taskqueue_enqueue_fast(tq, w) == 0);
+       return (taskqueue_enqueue(tq, w) == 0);
 }
 
 



Other related posts:

  • » [haiku-commits] haiku: hrev56208 - in src/libs/compat/freebsd_network: . compat/sys - waddlesplash