diff options
Diffstat (limited to 'lib/libzpool/common/taskq.c')
-rw-r--r-- | lib/libzpool/common/taskq.c | 103 |
1 files changed, 34 insertions, 69 deletions
diff --git a/lib/libzpool/common/taskq.c b/lib/libzpool/common/taskq.c index 2c5dfd86dcc0..8db5d11c1327 100644 --- a/lib/libzpool/common/taskq.c +++ b/lib/libzpool/common/taskq.c @@ -22,16 +22,19 @@ * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -/* - * Copyright 2011 Nexenta Systems, Inc. All rights reserved. - * Copyright 2012 Garrett D'Amore <garrett@damore.org>. 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 { @@ -48,18 +51,18 @@ struct taskq { int tq_maxalloc; kcondvar_t tq_maxalloc_cv; int tq_maxalloc_wait; - taskq_ent_t *tq_freelist; - taskq_ent_t tq_task; + task_t *tq_freelist; + task_t tq_task; }; -static taskq_ent_t * +static task_t * task_alloc(taskq_t *tq, int tqflags) { - taskq_ent_t *t; + task_t *t; int rv; again: if ((t = tq->tq_freelist) != NULL && tq->tq_nalloc >= tq->tq_minalloc) { - tq->tq_freelist = t->tqent_next; + tq->tq_freelist = t->task_next; } else { if (tq->tq_nalloc >= tq->tq_maxalloc) { if (!(tqflags & KM_SLEEP)) @@ -84,7 +87,7 @@ again: if ((t = tq->tq_freelist) != NULL && tq->tq_nalloc >= tq->tq_minalloc) { } mutex_exit(&tq->tq_lock); - t = kmem_alloc(sizeof (taskq_ent_t), tqflags); + t = kmem_alloc(sizeof (task_t), tqflags); mutex_enter(&tq->tq_lock); if (t != NULL) @@ -94,15 +97,15 @@ again: if ((t = tq->tq_freelist) != NULL && tq->tq_nalloc >= tq->tq_minalloc) { } static void -task_free(taskq_t *tq, taskq_ent_t *t) +task_free(taskq_t *tq, task_t *t) { if (tq->tq_nalloc <= tq->tq_minalloc) { - t->tqent_next = tq->tq_freelist; + t->task_next = tq->tq_freelist; tq->tq_freelist = t; } else { tq->tq_nalloc--; mutex_exit(&tq->tq_lock); - kmem_free(t, sizeof (taskq_ent_t)); + kmem_free(t, sizeof (task_t)); mutex_enter(&tq->tq_lock); } @@ -113,7 +116,7 @@ task_free(taskq_t *tq, taskq_ent_t *t) taskqid_t taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t tqflags) { - taskq_ent_t *t; + task_t *t; if (taskq_now) { func(arg); @@ -127,59 +130,26 @@ taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t tqflags) return (0); } if (tqflags & TQ_FRONT) { - t->tqent_next = tq->tq_task.tqent_next; - t->tqent_prev = &tq->tq_task; + t->task_next = tq->tq_task.task_next; + t->task_prev = &tq->tq_task; } else { - t->tqent_next = &tq->tq_task; - t->tqent_prev = tq->tq_task.tqent_prev; + t->task_next = &tq->tq_task; + t->task_prev = tq->tq_task.task_prev; } - t->tqent_next->tqent_prev = t; - t->tqent_prev->tqent_next = t; - t->tqent_func = func; - t->tqent_arg = arg; - t->tqent_flags = 0; + t->task_next->task_prev = t; + t->task_prev->task_next = t; + t->task_func = func; + t->task_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.tqent_next != &tq->tq_task || tq->tq_active != 0) + while (tq->tq_task.task_next != &tq->tq_task || tq->tq_active != 0) cv_wait(&tq->tq_wait_cv, &tq->tq_lock); mutex_exit(&tq->tq_lock); } @@ -188,32 +158,27 @@ static void * taskq_thread(void *arg) { taskq_t *tq = arg; - taskq_ent_t *t; - boolean_t prealloc; + task_t *t; mutex_enter(&tq->tq_lock); while (tq->tq_flags & TASKQ_ACTIVE) { - if ((t = tq->tq_task.tqent_next) == &tq->tq_task) { + if ((t = tq->tq_task.task_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->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; + t->task_prev->task_next = t->task_next; + t->task_next->task_prev = t->task_prev; mutex_exit(&tq->tq_lock); rw_enter(&tq->tq_threadlock, RW_READER); - t->tqent_func(t->tqent_arg); + t->task_func(t->task_arg); rw_exit(&tq->tq_threadlock); mutex_enter(&tq->tq_lock); - if (!prealloc) - task_free(tq, t); + task_free(tq, t); } tq->tq_nthreads--; cv_broadcast(&tq->tq_wait_cv); @@ -252,8 +217,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.tqent_next = &tq->tq_task; - tq->tq_task.tqent_prev = &tq->tq_task; + tq->tq_task.task_next = &tq->tq_task; + tq->tq_task.task_prev = &tq->tq_task; tq->tq_threadlist = kmem_alloc(nthreads * sizeof (thread_t), KM_SLEEP); if (flags & TASKQ_PREPOPULATE) { |