734 taskq_dispatch_prealloc() desired
943 zio_interrupt ends up calling taskq_dispatch with TQ_SLEEP illumos/illumos-gate@5aeb94743e Essentially FreeBSD taskqueues already operate in a mode that was added to Illumos with taskq_dispatch_ent change. We even exposed the superior FreeBSD interface as taskq_dispatch_safe. Now we just rename taskq_dispatch_safe to taskq_dispatch_ent and struct struct ostask to taskq_ent_t, so that code differences will be minimal. After this change sys/cddl/compat/opensolaris/sys/taskq.h header is no longer needed. Note that this commit is not an MFV because the upstream change was not individually committed to the vendor area. MFC after: 8 days
This commit is contained in:
parent
cfab30ba16
commit
34140e78ab
@ -23,6 +23,9 @@
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_ZFS_CONTEXT_H
|
||||
#define _SYS_ZFS_CONTEXT_H
|
||||
@ -367,6 +370,16 @@ typedef struct taskq taskq_t;
|
||||
typedef uintptr_t taskqid_t;
|
||||
typedef void (task_func_t)(void *);
|
||||
|
||||
typedef struct taskq_ent {
|
||||
struct taskq_ent *tqent_next;
|
||||
struct taskq_ent *tqent_prev;
|
||||
task_func_t *tqent_func;
|
||||
void *tqent_arg;
|
||||
uintptr_t tqent_flags;
|
||||
} taskq_ent_t;
|
||||
|
||||
#define TQENT_FLAG_PREALLOC 0x1 /* taskq_dispatch_ent used */
|
||||
|
||||
#define TASKQ_PREPOPULATE 0x0001
|
||||
#define TASKQ_CPR_SAFE 0x0002 /* Use CPR safe protocol */
|
||||
#define TASKQ_DYNAMIC 0x0004 /* Use dynamic thread scheduling */
|
||||
@ -378,6 +391,7 @@ typedef void (task_func_t)(void *);
|
||||
#define TQ_NOQUEUE 0x02 /* Do not enqueue if can't dispatch */
|
||||
#define TQ_FRONT 0x08 /* Queue in front */
|
||||
|
||||
|
||||
extern taskq_t *system_taskq;
|
||||
|
||||
extern taskq_t *taskq_create(const char *, int, pri_t, int, int, uint_t);
|
||||
@ -386,6 +400,8 @@ extern taskq_t *taskq_create(const char *, int, pri_t, int, int, uint_t);
|
||||
#define taskq_create_sysdc(a, b, d, e, p, dc, f) \
|
||||
(taskq_create(a, b, maxclsyspri, d, e, f))
|
||||
extern taskqid_t taskq_dispatch(taskq_t *, task_func_t, void *, uint_t);
|
||||
extern void taskq_dispatch_ent(taskq_t *, task_func_t, void *, uint_t,
|
||||
taskq_ent_t *);
|
||||
extern void taskq_destroy(taskq_t *);
|
||||
extern void taskq_wait(taskq_t *);
|
||||
extern int taskq_member(taskq_t *, void *);
|
||||
|
@ -22,19 +22,15 @@
|
||||
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
/*
|
||||
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <sys/zfs_context.h>
|
||||
|
||||
int taskq_now;
|
||||
taskq_t *system_taskq;
|
||||
|
||||
typedef struct task {
|
||||
struct task *task_next;
|
||||
struct task *task_prev;
|
||||
task_func_t *task_func;
|
||||
void *task_arg;
|
||||
} task_t;
|
||||
|
||||
#define TASKQ_ACTIVE 0x00010000
|
||||
|
||||
struct taskq {
|
||||
@ -51,18 +47,18 @@ struct taskq {
|
||||
int tq_maxalloc;
|
||||
kcondvar_t tq_maxalloc_cv;
|
||||
int tq_maxalloc_wait;
|
||||
task_t *tq_freelist;
|
||||
task_t tq_task;
|
||||
taskq_ent_t *tq_freelist;
|
||||
taskq_ent_t tq_task;
|
||||
};
|
||||
|
||||
static task_t *
|
||||
static taskq_ent_t *
|
||||
task_alloc(taskq_t *tq, int tqflags)
|
||||
{
|
||||
task_t *t;
|
||||
taskq_ent_t *t;
|
||||
int rv;
|
||||
|
||||
again: if ((t = tq->tq_freelist) != NULL && tq->tq_nalloc >= tq->tq_minalloc) {
|
||||
tq->tq_freelist = t->task_next;
|
||||
tq->tq_freelist = t->tqent_next;
|
||||
} else {
|
||||
if (tq->tq_nalloc >= tq->tq_maxalloc) {
|
||||
if (!(tqflags & KM_SLEEP))
|
||||
@ -87,7 +83,7 @@ again: if ((t = tq->tq_freelist) != NULL && tq->tq_nalloc >= tq->tq_minalloc) {
|
||||
}
|
||||
mutex_exit(&tq->tq_lock);
|
||||
|
||||
t = kmem_alloc(sizeof (task_t), tqflags & KM_SLEEP);
|
||||
t = kmem_alloc(sizeof (taskq_ent_t), tqflags & KM_SLEEP);
|
||||
|
||||
mutex_enter(&tq->tq_lock);
|
||||
if (t != NULL)
|
||||
@ -97,15 +93,15 @@ again: if ((t = tq->tq_freelist) != NULL && tq->tq_nalloc >= tq->tq_minalloc) {
|
||||
}
|
||||
|
||||
static void
|
||||
task_free(taskq_t *tq, task_t *t)
|
||||
task_free(taskq_t *tq, taskq_ent_t *t)
|
||||
{
|
||||
if (tq->tq_nalloc <= tq->tq_minalloc) {
|
||||
t->task_next = tq->tq_freelist;
|
||||
t->tqent_next = tq->tq_freelist;
|
||||
tq->tq_freelist = t;
|
||||
} else {
|
||||
tq->tq_nalloc--;
|
||||
mutex_exit(&tq->tq_lock);
|
||||
kmem_free(t, sizeof (task_t));
|
||||
kmem_free(t, sizeof (taskq_ent_t));
|
||||
mutex_enter(&tq->tq_lock);
|
||||
}
|
||||
|
||||
@ -116,7 +112,7 @@ task_free(taskq_t *tq, task_t *t)
|
||||
taskqid_t
|
||||
taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t tqflags)
|
||||
{
|
||||
task_t *t;
|
||||
taskq_ent_t *t;
|
||||
|
||||
if (taskq_now) {
|
||||
func(arg);
|
||||
@ -130,26 +126,58 @@ taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t tqflags)
|
||||
return (0);
|
||||
}
|
||||
if (tqflags & TQ_FRONT) {
|
||||
t->task_next = tq->tq_task.task_next;
|
||||
t->task_prev = &tq->tq_task;
|
||||
t->tqent_next = tq->tq_task.tqent_next;
|
||||
t->tqent_prev = &tq->tq_task;
|
||||
} else {
|
||||
t->task_next = &tq->tq_task;
|
||||
t->task_prev = tq->tq_task.task_prev;
|
||||
t->tqent_next = &tq->tq_task;
|
||||
t->tqent_prev = tq->tq_task.tqent_prev;
|
||||
}
|
||||
t->task_next->task_prev = t;
|
||||
t->task_prev->task_next = t;
|
||||
t->task_func = func;
|
||||
t->task_arg = arg;
|
||||
t->tqent_next->tqent_prev = t;
|
||||
t->tqent_prev->tqent_next = t;
|
||||
t->tqent_func = func;
|
||||
t->tqent_arg = arg;
|
||||
cv_signal(&tq->tq_dispatch_cv);
|
||||
mutex_exit(&tq->tq_lock);
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags,
|
||||
taskq_ent_t *t)
|
||||
{
|
||||
ASSERT(func != NULL);
|
||||
ASSERT(!(tq->tq_flags & TASKQ_DYNAMIC));
|
||||
|
||||
/*
|
||||
* Mark it as a prealloc'd task. This is important
|
||||
* to ensure that we don't free it later.
|
||||
*/
|
||||
t->tqent_flags |= TQENT_FLAG_PREALLOC;
|
||||
/*
|
||||
* Enqueue the task to the underlying queue.
|
||||
*/
|
||||
mutex_enter(&tq->tq_lock);
|
||||
|
||||
if (flags & TQ_FRONT) {
|
||||
t->tqent_next = tq->tq_task.tqent_next;
|
||||
t->tqent_prev = &tq->tq_task;
|
||||
} else {
|
||||
t->tqent_next = &tq->tq_task;
|
||||
t->tqent_prev = tq->tq_task.tqent_prev;
|
||||
}
|
||||
t->tqent_next->tqent_prev = t;
|
||||
t->tqent_prev->tqent_next = t;
|
||||
t->tqent_func = func;
|
||||
t->tqent_arg = arg;
|
||||
cv_signal(&tq->tq_dispatch_cv);
|
||||
mutex_exit(&tq->tq_lock);
|
||||
}
|
||||
|
||||
void
|
||||
taskq_wait(taskq_t *tq)
|
||||
{
|
||||
mutex_enter(&tq->tq_lock);
|
||||
while (tq->tq_task.task_next != &tq->tq_task || tq->tq_active != 0)
|
||||
while (tq->tq_task.tqent_next != &tq->tq_task || tq->tq_active != 0)
|
||||
cv_wait(&tq->tq_wait_cv, &tq->tq_lock);
|
||||
mutex_exit(&tq->tq_lock);
|
||||
}
|
||||
@ -158,27 +186,32 @@ static void *
|
||||
taskq_thread(void *arg)
|
||||
{
|
||||
taskq_t *tq = arg;
|
||||
task_t *t;
|
||||
taskq_ent_t *t;
|
||||
boolean_t prealloc;
|
||||
|
||||
mutex_enter(&tq->tq_lock);
|
||||
while (tq->tq_flags & TASKQ_ACTIVE) {
|
||||
if ((t = tq->tq_task.task_next) == &tq->tq_task) {
|
||||
if ((t = tq->tq_task.tqent_next) == &tq->tq_task) {
|
||||
if (--tq->tq_active == 0)
|
||||
cv_broadcast(&tq->tq_wait_cv);
|
||||
cv_wait(&tq->tq_dispatch_cv, &tq->tq_lock);
|
||||
tq->tq_active++;
|
||||
continue;
|
||||
}
|
||||
t->task_prev->task_next = t->task_next;
|
||||
t->task_next->task_prev = t->task_prev;
|
||||
t->tqent_prev->tqent_next = t->tqent_next;
|
||||
t->tqent_next->tqent_prev = t->tqent_prev;
|
||||
t->tqent_next = NULL;
|
||||
t->tqent_prev = NULL;
|
||||
prealloc = t->tqent_flags & TQENT_FLAG_PREALLOC;
|
||||
mutex_exit(&tq->tq_lock);
|
||||
|
||||
rw_enter(&tq->tq_threadlock, RW_READER);
|
||||
t->task_func(t->task_arg);
|
||||
t->tqent_func(t->tqent_arg);
|
||||
rw_exit(&tq->tq_threadlock);
|
||||
|
||||
mutex_enter(&tq->tq_lock);
|
||||
task_free(tq, t);
|
||||
if (!prealloc)
|
||||
task_free(tq, t);
|
||||
}
|
||||
tq->tq_nthreads--;
|
||||
cv_broadcast(&tq->tq_wait_cv);
|
||||
@ -217,8 +250,8 @@ taskq_create(const char *name, int nthreads, pri_t pri,
|
||||
tq->tq_nthreads = nthreads;
|
||||
tq->tq_minalloc = minalloc;
|
||||
tq->tq_maxalloc = maxalloc;
|
||||
tq->tq_task.task_next = &tq->tq_task;
|
||||
tq->tq_task.task_prev = &tq->tq_task;
|
||||
tq->tq_task.tqent_next = &tq->tq_task;
|
||||
tq->tq_task.tqent_prev = &tq->tq_task;
|
||||
tq->tq_threadlist = kmem_alloc(nthreads * sizeof (thread_t), KM_SLEEP);
|
||||
|
||||
if (flags & TASKQ_PREPOPULATE) {
|
||||
|
@ -46,7 +46,7 @@ static void
|
||||
system_taskq_init(void *arg)
|
||||
{
|
||||
|
||||
taskq_zone = uma_zcreate("taskq_zone", sizeof(struct ostask),
|
||||
taskq_zone = uma_zcreate("taskq_zone", sizeof(taskq_ent_t),
|
||||
NULL, NULL, NULL, NULL, 0, 0);
|
||||
system_taskq = taskq_create("system_taskq", mp_ncpus, 0, 0, 0, 0);
|
||||
}
|
||||
@ -104,9 +104,9 @@ taskq_member(taskq_t *tq, kthread_t *thread)
|
||||
static void
|
||||
taskq_run(void *arg, int pending __unused)
|
||||
{
|
||||
struct ostask *task = arg;
|
||||
taskq_ent_t *task = arg;
|
||||
|
||||
task->ost_func(task->ost_arg);
|
||||
task->tqent_func(task->tqent_arg);
|
||||
|
||||
uma_zfree(taskq_zone, task);
|
||||
}
|
||||
@ -114,7 +114,7 @@ taskq_run(void *arg, int pending __unused)
|
||||
taskqid_t
|
||||
taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags)
|
||||
{
|
||||
struct ostask *task;
|
||||
taskq_ent_t *task;
|
||||
int mflag, prio;
|
||||
|
||||
if ((flags & (TQ_SLEEP | TQ_NOQUEUE)) == TQ_SLEEP)
|
||||
@ -131,26 +131,26 @@ taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags)
|
||||
if (task == NULL)
|
||||
return (0);
|
||||
|
||||
task->ost_func = func;
|
||||
task->ost_arg = arg;
|
||||
task->tqent_func = func;
|
||||
task->tqent_arg = arg;
|
||||
|
||||
TASK_INIT(&task->ost_task, prio, taskq_run, task);
|
||||
taskqueue_enqueue(tq->tq_queue, &task->ost_task);
|
||||
TASK_INIT(&task->tqent_task, prio, taskq_run, task);
|
||||
taskqueue_enqueue(tq->tq_queue, &task->tqent_task);
|
||||
|
||||
return ((taskqid_t)(void *)task);
|
||||
}
|
||||
|
||||
static void
|
||||
taskq_run_safe(void *arg, int pending __unused)
|
||||
taskq_run_ent(void *arg, int pending __unused)
|
||||
{
|
||||
struct ostask *task = arg;
|
||||
taskq_ent_t *task = arg;
|
||||
|
||||
task->ost_func(task->ost_arg);
|
||||
task->tqent_func(task->tqent_arg);
|
||||
}
|
||||
|
||||
taskqid_t
|
||||
taskq_dispatch_safe(taskq_t *tq, task_func_t func, void *arg, u_int flags,
|
||||
struct ostask *task)
|
||||
void
|
||||
taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, u_int flags,
|
||||
taskq_ent_t *task)
|
||||
{
|
||||
int prio;
|
||||
|
||||
@ -160,11 +160,9 @@ taskq_dispatch_safe(taskq_t *tq, task_func_t func, void *arg, u_int flags,
|
||||
*/
|
||||
prio = !!(flags & TQ_FRONT);
|
||||
|
||||
task->ost_func = func;
|
||||
task->ost_arg = arg;
|
||||
task->tqent_func = func;
|
||||
task->tqent_arg = arg;
|
||||
|
||||
TASK_INIT(&task->ost_task, prio, taskq_run_safe, task);
|
||||
taskqueue_enqueue(tq->tq_queue, &task->ost_task);
|
||||
|
||||
return ((taskqid_t)(void *)task);
|
||||
TASK_INIT(&task->tqent_task, prio, taskq_run_ent, task);
|
||||
taskqueue_enqueue(tq->tq_queue, &task->tqent_task);
|
||||
}
|
||||
|
@ -1,43 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||
* 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 AUTHORS 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 AUTHORS 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 _OPENSOLARIS_SYS_TASKQ_H_
|
||||
#define _OPENSOLARIS_SYS_TASKQ_H_
|
||||
|
||||
#include_next <sys/taskq.h>
|
||||
|
||||
struct ostask {
|
||||
struct task ost_task;
|
||||
task_func_t *ost_func;
|
||||
void *ost_arg;
|
||||
};
|
||||
|
||||
taskqid_t taskq_dispatch_safe(taskq_t *tq, task_func_t func, void *arg,
|
||||
u_int flags, struct ostask *task);
|
||||
|
||||
#endif /* _OPENSOLARIS_SYS_TASKQ_H_ */
|
@ -825,7 +825,7 @@ static taskq_t *
|
||||
spa_taskq_create(spa_t *spa, const char *name, enum zti_modes mode,
|
||||
uint_t value)
|
||||
{
|
||||
uint_t flags = TASKQ_PREPOPULATE;
|
||||
uint_t flags = 0;
|
||||
boolean_t batch = B_FALSE;
|
||||
|
||||
switch (mode) {
|
||||
|
@ -24,6 +24,7 @@
|
||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _ZIO_H
|
||||
@ -474,10 +475,9 @@ struct zio {
|
||||
zio_cksum_report_t *io_cksum_report;
|
||||
uint64_t io_ena;
|
||||
|
||||
#ifdef _KERNEL
|
||||
/* FreeBSD only. */
|
||||
struct ostask io_task;
|
||||
#endif
|
||||
/* Taskq dispatching state */
|
||||
taskq_ent_t io_tqent;
|
||||
|
||||
avl_node_t io_trim_node;
|
||||
list_node_t io_trim_link;
|
||||
};
|
||||
|
@ -21,6 +21,7 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <sys/zfs_context.h>
|
||||
@ -1224,7 +1225,7 @@ zio_taskq_dispatch(zio_t *zio, enum zio_taskq_type q, boolean_t cutinline)
|
||||
{
|
||||
spa_t *spa = zio->io_spa;
|
||||
zio_type_t t = zio->io_type;
|
||||
int flags = TQ_SLEEP | (cutinline ? TQ_FRONT : 0);
|
||||
int flags = (cutinline ? TQ_FRONT : 0);
|
||||
|
||||
ASSERT(q == ZIO_TASKQ_ISSUE || q == ZIO_TASKQ_INTERRUPT);
|
||||
|
||||
@ -1250,13 +1251,19 @@ zio_taskq_dispatch(zio_t *zio, enum zio_taskq_type q, boolean_t cutinline)
|
||||
q++;
|
||||
|
||||
ASSERT3U(q, <, ZIO_TASKQ_TYPES);
|
||||
#ifdef _KERNEL
|
||||
(void) taskq_dispatch_safe(spa->spa_zio_taskq[t][q],
|
||||
(task_func_t *)zio_execute, zio, flags, &zio->io_task);
|
||||
|
||||
/*
|
||||
* NB: We are assuming that the zio can only be dispatched
|
||||
* to a single taskq at a time. It would be a grievous error
|
||||
* to dispatch the zio to another taskq at the same time.
|
||||
*/
|
||||
#if defined(illumos) || !defined(_KERNEL)
|
||||
ASSERT(zio->io_tqent.tqent_next == NULL);
|
||||
#else
|
||||
(void) taskq_dispatch(spa->spa_zio_taskq[t][q],
|
||||
(task_func_t *)zio_execute, zio, flags);
|
||||
ASSERT(zio->io_tqent.tqent_task.ta_pending == 0);
|
||||
#endif
|
||||
taskq_dispatch_ent(spa->spa_zio_taskq[t][q],
|
||||
(task_func_t *)zio_execute, zio, flags, &zio->io_tqent);
|
||||
}
|
||||
|
||||
static boolean_t
|
||||
@ -3174,16 +3181,15 @@ zio_done(zio_t *zio)
|
||||
* Reexecution is potentially a huge amount of work.
|
||||
* Hand it off to the otherwise-unused claim taskq.
|
||||
*/
|
||||
#ifdef _KERNEL
|
||||
(void) taskq_dispatch_safe(
|
||||
spa->spa_zio_taskq[ZIO_TYPE_CLAIM][ZIO_TASKQ_ISSUE],
|
||||
(task_func_t *)zio_reexecute, zio, TQ_SLEEP,
|
||||
&zio->io_task);
|
||||
#if defined(illumos) || !defined(_KERNEL)
|
||||
ASSERT(zio->io_tqent.tqent_next == NULL);
|
||||
#else
|
||||
(void) taskq_dispatch(
|
||||
spa->spa_zio_taskq[ZIO_TYPE_CLAIM][ZIO_TASKQ_ISSUE],
|
||||
(task_func_t *)zio_reexecute, zio, TQ_SLEEP);
|
||||
ASSERT(zio->io_tqent.tqent_task.ta_pending == 0);
|
||||
#endif
|
||||
(void) taskq_dispatch_ent(
|
||||
spa->spa_zio_taskq[ZIO_TYPE_CLAIM][ZIO_TASKQ_ISSUE],
|
||||
(task_func_t *)zio_reexecute, zio, 0,
|
||||
&zio->io_tqent);
|
||||
}
|
||||
return (ZIO_PIPELINE_STOP);
|
||||
}
|
||||
|
@ -45,6 +45,12 @@ typedef struct taskq taskq_t;
|
||||
typedef uintptr_t taskqid_t;
|
||||
typedef void (task_func_t)(void *);
|
||||
|
||||
typedef struct taskq_ent {
|
||||
struct task tqent_task;
|
||||
task_func_t *tqent_func;
|
||||
void *tqent_arg;
|
||||
} taskq_ent_t;
|
||||
|
||||
struct proc;
|
||||
|
||||
/*
|
||||
@ -80,6 +86,8 @@ taskq_t *taskq_create_proc(const char *, int, pri_t, int, int,
|
||||
taskq_t *taskq_create_sysdc(const char *, int, int, int,
|
||||
struct proc *, uint_t, uint_t);
|
||||
taskqid_t taskq_dispatch(taskq_t *, task_func_t, void *, uint_t);
|
||||
void taskq_dispatch_ent(taskq_t *, task_func_t, void *, uint_t,
|
||||
taskq_ent_t *);
|
||||
void nulltask(void *);
|
||||
void taskq_destroy(taskq_t *);
|
||||
void taskq_wait(taskq_t *);
|
||||
|
Loading…
Reference in New Issue
Block a user