MFC r196295:

Remove OpenSolaris taskq port (it performs very poorly in our kernel) and
replace it with wrappers around our taskqueue(9).
To make it possible implement taskqueue_member() function which returns 1
if the given thread was created by the given taskqueue.

Approved by:	re (kib)
This commit is contained in:
Pawel Jakub Dawidek 2009-08-17 09:03:47 +00:00
parent ea5f504fed
commit e43f173602
9 changed files with 188 additions and 1190 deletions

View File

@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd June 13, 2008
.Dd August 17, 2009
.Dt TASKQUEUE 9
.Os
.Sh NAME
@ -71,6 +71,8 @@ struct task {
.Fn taskqueue_run_fast "struct taskqueue *queue"
.Ft void
.Fn taskqueue_drain "struct taskqueue *queue" "struct task *task"
.Ft int
.Fn taskqueue_member "struct taskqueue *queue" "struct thread *td"
.Fn TASK_INIT "struct task *task" "int priority" "task_fn_t *func" "void *context"
.Fn TASKQUEUE_DECLARE "name"
.Fn TASKQUEUE_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init"
@ -182,6 +184,18 @@ There is no guarantee that the task will not be
enqueued after call to
.Fn taskqueue_drain .
.Pp
The
.Fn taskqueue_member
function returns
.No 1
is the given thread
.Fa td
is part of the given taskqeueue
.Fa queue
and
.No 0
otherwise.
.Pp
A convenience macro,
.Fn TASK_INIT "task" "priority" "func" "context"
is provided to initialise a

View File

@ -0,0 +1,135 @@
/*-
* Copyright (c) 2009 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/kmem.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/taskq.h>
#include <vm/uma.h>
static uma_zone_t taskq_zone;
struct ostask {
struct task ost_task;
task_func_t *ost_func;
void *ost_arg;
};
taskq_t *system_taskq = NULL;
static void
system_taskq_init(void *arg)
{
system_taskq = (taskq_t *)taskqueue_thread;
taskq_zone = uma_zcreate("taskq_zone", sizeof(struct ostask),
NULL, NULL, NULL, NULL, 0, 0);
}
SYSINIT(system_taskq_init, SI_SUB_CONFIGURE, SI_ORDER_ANY, system_taskq_init, NULL);
static void
system_taskq_fini(void *arg)
{
uma_zdestroy(taskq_zone);
}
SYSUNINIT(system_taskq_fini, SI_SUB_CONFIGURE, SI_ORDER_ANY, system_taskq_fini, NULL);
taskq_t *
taskq_create(const char *name, int nthreads, pri_t pri, int minalloc __unused,
int maxalloc __unused, uint_t flags)
{
taskq_t *tq;
if ((flags & TASKQ_THREADS_CPU_PCT) != 0) {
/* TODO: Calculate number od threads. */
printf("%s: TASKQ_THREADS_CPU_PCT\n", __func__);
}
tq = kmem_alloc(sizeof(*tq), KM_SLEEP);
tq->tq_queue = taskqueue_create(name, M_WAITOK, taskqueue_thread_enqueue,
&tq->tq_queue);
(void) taskqueue_start_threads(&tq->tq_queue, nthreads, pri, name);
return ((taskq_t *)tq);
}
void
taskq_destroy(taskq_t *tq)
{
taskqueue_free(tq->tq_queue);
kmem_free(tq, sizeof(*tq));
}
int
taskq_member(taskq_t *tq, kthread_t *thread)
{
return (taskqueue_member(tq->tq_queue, thread));
}
static void
taskq_run(void *arg, int pending __unused)
{
struct ostask *task = arg;
task->ost_func(task->ost_arg);
uma_zfree(taskq_zone, task);
}
taskqid_t
taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags)
{
struct ostask *task;
int mflag;
if ((flags & (TQ_SLEEP | TQ_NOQUEUE)) == TQ_SLEEP)
mflag = M_WAITOK;
else
mflag = M_NOWAIT;
task = uma_zalloc(taskq_zone, mflag);
if (task == NULL)
return (0);
task->ost_func = func;
task->ost_arg = arg;
TASK_INIT(&task->ost_task, 0, taskq_run, task);
taskqueue_enqueue(tq->tq_queue, &task->ost_task);
return ((taskqid_t)(void *)task);
}

View File

@ -1,137 +0,0 @@
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* $FreeBSD$
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_TASKQ_IMPL_H
#define _SYS_TASKQ_IMPL_H
#pragma ident "@(#)taskq_impl.h 1.6 05/06/08 SMI"
#include <sys/mutex.h>
#include <sys/rwlock.h>
#include <sys/condvar.h>
#include <sys/taskq.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct taskq_bucket taskq_bucket_t;
typedef struct taskq_ent {
struct taskq_ent *tqent_next;
struct taskq_ent *tqent_prev;
task_func_t *tqent_func;
void *tqent_arg;
taskq_bucket_t *tqent_bucket;
kthread_t *tqent_thread;
kcondvar_t tqent_cv;
} taskq_ent_t;
/*
* Taskq Statistics fields are not protected by any locks.
*/
typedef struct tqstat {
uint_t tqs_hits;
uint_t tqs_misses;
uint_t tqs_overflow; /* no threads to allocate */
uint_t tqs_tcreates; /* threads created */
uint_t tqs_tdeaths; /* threads died */
uint_t tqs_maxthreads; /* max # of alive threads */
uint_t tqs_nomem; /* # of times there were no memory */
uint_t tqs_disptcreates;
} tqstat_t;
/*
* Per-CPU hash bucket manages taskq_bent_t structures using freelist.
*/
struct taskq_bucket {
kmutex_t tqbucket_lock;
taskq_t *tqbucket_taskq; /* Enclosing taskq */
taskq_ent_t tqbucket_freelist;
uint_t tqbucket_nalloc; /* # of allocated entries */
uint_t tqbucket_nfree; /* # of free entries */
kcondvar_t tqbucket_cv;
ushort_t tqbucket_flags;
hrtime_t tqbucket_totaltime;
tqstat_t tqbucket_stat;
};
/*
* Bucket flags.
*/
#define TQBUCKET_CLOSE 0x01
#define TQBUCKET_SUSPEND 0x02
/*
* taskq implementation flags: bit range 16-31
*/
#define TASKQ_ACTIVE 0x00010000
#define TASKQ_SUSPENDED 0x00020000
#define TASKQ_NOINSTANCE 0x00040000
struct taskq {
char tq_name[TASKQ_NAMELEN + 1];
kmutex_t tq_lock;
krwlock_t tq_threadlock;
kcondvar_t tq_dispatch_cv;
kcondvar_t tq_wait_cv;
uint_t tq_flags;
int tq_active;
int tq_nthreads;
int tq_nalloc;
int tq_minalloc;
int tq_maxalloc;
taskq_ent_t *tq_freelist;
taskq_ent_t tq_task;
int tq_maxsize;
pri_t tq_pri; /* Scheduling priority */
taskq_bucket_t *tq_buckets; /* Per-cpu array of buckets */
uint_t tq_nbuckets; /* # of buckets (2^n) */
union {
kthread_t *_tq_thread;
kthread_t **_tq_threadlist;
} tq_thr;
/*
* Statistics.
*/
hrtime_t tq_totaltime; /* Time spent processing tasks */
int tq_tasks; /* Total # of tasks posted */
int tq_executed; /* Total # of tasks executed */
int tq_maxtasks; /* Max number of tasks in the queue */
int tq_tcreates;
int tq_tdeaths;
};
#define tq_thread tq_thr._tq_thread
#define tq_threadlist tq_thr._tq_threadlist
#ifdef __cplusplus
}
#endif
#endif /* _SYS_TASKQ_IMPL_H */

View File

@ -49,6 +49,7 @@ extern "C" {
#include <sys/conf.h>
#include <sys/mutex.h>
#include <sys/rwlock.h>
#include <sys/kcondvar.h>
#include <sys/random.h>
#include <sys/byteorder.h>
#include <sys/systm.h>

File diff suppressed because it is too large Load Diff

View File

@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@ -18,22 +17,18 @@
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* $FreeBSD$
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_TASKQ_H
#define _SYS_TASKQ_H
#pragma ident "@(#)taskq.h 1.5 05/06/08 SMI"
#include <sys/param.h>
#include <sys/types.h>
#include <sys/proc.h>
#include <sys/kcondvar.h>
#include <sys/taskqueue.h>
#ifdef __cplusplus
extern "C" {
@ -41,6 +36,11 @@ extern "C" {
#define TASKQ_NAMELEN 31
struct taskqueue;
struct taskq {
struct taskqueue *tq_queue;
};
typedef struct taskq taskq_t;
typedef uintptr_t taskqid_t;
typedef void (task_func_t)(void *);
@ -51,6 +51,7 @@ typedef void (task_func_t)(void *);
#define TASKQ_PREPOPULATE 0x0001 /* Prepopulate with threads and data */
#define TASKQ_CPR_SAFE 0x0002 /* Use CPR safe protocol */
#define TASKQ_DYNAMIC 0x0004 /* Use dynamic thread scheduling */
#define TASKQ_THREADS_CPU_PCT 0x0008 /* number of threads as % of ncpu */
/*
* Flags for taskq_dispatch. TQ_SLEEP/TQ_NOSLEEP should be same as
@ -65,6 +66,9 @@ typedef void (task_func_t)(void *);
extern taskq_t *system_taskq;
extern void taskq_init(void);
extern void taskq_mp_init(void);
extern taskq_t *taskq_create(const char *, int, pri_t, int, int, uint_t);
extern taskq_t *taskq_create_instance(const char *, int, int, pri_t, int,
int, uint_t);

View File

@ -472,3 +472,23 @@ taskqueue_fast_run(void *dummy)
TASKQUEUE_FAST_DEFINE(fast, taskqueue_fast_enqueue, NULL,
swi_add(NULL, "Fast task queue", taskqueue_fast_run, NULL,
SWI_TQ_FAST, INTR_MPSAFE, &taskqueue_fast_ih));
int
taskqueue_member(struct taskqueue *queue, struct thread *td)
{
int i, j, ret = 0;
TQ_LOCK(queue);
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;
}
TQ_UNLOCK(queue);
return (ret);
}

View File

@ -23,6 +23,7 @@ SRCS+= opensolaris_kstat.c
SRCS+= opensolaris_lookup.c
SRCS+= opensolaris_policy.c
SRCS+= opensolaris_string.c
SRCS+= opensolaris_taskq.c
SRCS+= opensolaris_vfs.c
SRCS+= opensolaris_zone.c
@ -42,7 +43,6 @@ SRCS+= vnode.c
SRCS+= callb.c
SRCS+= list.c
SRCS+= nvpair_alloc_system.c
SRCS+= taskq.c
.PATH: ${SUNW}/uts/common/zmod
SRCS+= adler32.c

View File

@ -37,6 +37,7 @@
#include <sys/_task.h>
struct taskqueue;
struct thread;
/*
* A notification callback function which is called from
@ -60,6 +61,7 @@ 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);
/*
* Functions for dedicated thread taskqueues