Add system taskq support

This commit is contained in:
Brian Behlendorf 2009-01-05 15:08:03 -08:00
parent 8a2b328b18
commit e9cb2b4f64
4 changed files with 89 additions and 12 deletions

View File

@ -81,12 +81,18 @@ typedef struct taskq {
wait_queue_head_t tq_wait_waitq; /* wait waitq */ wait_queue_head_t tq_wait_waitq; /* wait waitq */
} taskq_t; } taskq_t;
/* Global system-wide dynamic task queue available for all consumers */
extern taskq_t *system_taskq;
extern taskqid_t __taskq_dispatch(taskq_t *, task_func_t, void *, uint_t); extern taskqid_t __taskq_dispatch(taskq_t *, task_func_t, void *, uint_t);
extern taskq_t *__taskq_create(const char *, int, pri_t, int, int, uint_t); extern taskq_t *__taskq_create(const char *, int, pri_t, int, int, uint_t);
extern void __taskq_destroy(taskq_t *); extern void __taskq_destroy(taskq_t *);
extern void __taskq_wait(taskq_t *); extern void __taskq_wait(taskq_t *);
extern int __taskq_member(taskq_t *, void *); extern int __taskq_member(taskq_t *, void *);
int spl_taskq_init(void);
void spl_taskq_fini(void);
#define taskq_member(tq, t) __taskq_member(tq, t) #define taskq_member(tq, t) __taskq_member(tq, t)
#define taskq_wait_id(tq, id) __taskq_wait_id(tq, id) #define taskq_wait_id(tq, id) __taskq_wait_id(tq, id)
#define taskq_wait(tq) __taskq_wait(tq) #define taskq_wait(tq) __taskq_wait(tq)

View File

@ -29,6 +29,7 @@
#include <sys/vnode.h> #include <sys/vnode.h>
#include <sys/kmem.h> #include <sys/kmem.h>
#include <sys/mutex.h> #include <sys/mutex.h>
#include <sys/taskq.h>
#include <sys/debug.h> #include <sys/debug.h>
#include <sys/proc.h> #include <sys/proc.h>
#include <sys/kstat.h> #include <sys/kstat.h>
@ -225,26 +226,31 @@ static int __init spl_init(void)
if ((rc = spl_mutex_init())) if ((rc = spl_mutex_init()))
GOTO(out2 , rc); GOTO(out2 , rc);
if ((rc = vn_init())) if ((rc = spl_taskq_init()))
GOTO(out3, rc); GOTO(out3, rc);
if ((rc = proc_init())) if ((rc = vn_init()))
GOTO(out4, rc); GOTO(out4, rc);
if ((rc = kstat_init())) if ((rc = proc_init()))
GOTO(out5, rc); GOTO(out5, rc);
if ((rc = kstat_init()))
GOTO(out6, rc);
if ((rc = set_hostid())) if ((rc = set_hostid()))
GOTO(out6, rc = -EADDRNOTAVAIL); GOTO(out7, rc = -EADDRNOTAVAIL);
printk("SPL: Loaded Solaris Porting Layer v%s\n", VERSION); printk("SPL: Loaded Solaris Porting Layer v%s\n", VERSION);
RETURN(rc); RETURN(rc);
out6: out7:
kstat_fini(); kstat_fini();
out5: out6:
proc_fini(); proc_fini();
out4: out5:
vn_fini(); vn_fini();
out4:
spl_taskq_fini();
out3: out3:
spl_mutex_fini(); spl_mutex_fini();
out2: out2:
@ -265,6 +271,7 @@ static void spl_fini(void)
kstat_fini(); kstat_fini();
proc_fini(); proc_fini();
vn_fini(); vn_fini();
spl_taskq_fini();
spl_mutex_fini(); spl_mutex_fini();
spl_kmem_fini(); spl_kmem_fini();
debug_fini(); debug_fini();

View File

@ -33,6 +33,10 @@
#define DEBUG_SUBSYSTEM S_TASKQ #define DEBUG_SUBSYSTEM S_TASKQ
/* Global system-wide dynamic task queue available for all consumers */
taskq_t *system_taskq;
EXPORT_SYMBOL(system_taskq);
typedef struct spl_task { typedef struct spl_task {
spinlock_t t_lock; spinlock_t t_lock;
struct list_head t_list; struct list_head t_list;
@ -464,3 +468,24 @@ __taskq_destroy(taskq_t *tq)
EXIT; EXIT;
} }
EXPORT_SYMBOL(__taskq_destroy); EXPORT_SYMBOL(__taskq_destroy);
int
spl_taskq_init(void)
{
ENTRY;
system_taskq = taskq_create("system_taskq", 64, minclsyspri, 4, 512,
TASKQ_DYNAMIC | TASKQ_PREPOPULATE);
if (system_taskq == NULL)
RETURN(1);
RETURN(0);
}
void
spl_taskq_fini(void)
{
ENTRY;
taskq_destroy(system_taskq);
EXIT;
}

View File

@ -38,6 +38,10 @@
#define SPLAT_TASKQ_TEST2_NAME "multiple" #define SPLAT_TASKQ_TEST2_NAME "multiple"
#define SPLAT_TASKQ_TEST2_DESC "Multiple task queues, multiple tasks" #define SPLAT_TASKQ_TEST2_DESC "Multiple task queues, multiple tasks"
#define SPLAT_TASKQ_TEST3_ID 0x0203
#define SPLAT_TASKQ_TEST3_NAME "system"
#define SPLAT_TASKQ_TEST3_DESC "System task queue, multiple tasks"
typedef struct splat_taskq_arg { typedef struct splat_taskq_arg {
int flag; int flag;
int id; int id;
@ -49,14 +53,14 @@ typedef struct splat_taskq_arg {
* task completes, ensure task ran properly, cleanup taskq, * task completes, ensure task ran properly, cleanup taskq,
*/ */
static void static void
splat_taskq_test1_func(void *arg) splat_taskq_test13_func(void *arg)
{ {
splat_taskq_arg_t *tq_arg = (splat_taskq_arg_t *)arg; splat_taskq_arg_t *tq_arg = (splat_taskq_arg_t *)arg;
ASSERT(tq_arg); ASSERT(tq_arg);
splat_vprint(tq_arg->file, SPLAT_TASKQ_TEST1_NAME, splat_vprint(tq_arg->file, SPLAT_TASKQ_TEST1_NAME,
"Taskq '%s' function '%s' setting flag\n", "Taskq '%s' function '%s' setting flag\n",
tq_arg->name, sym2str(splat_taskq_test1_func)); tq_arg->name, sym2str(splat_taskq_test13_func));
tq_arg->flag = 1; tq_arg->flag = 1;
} }
@ -84,12 +88,12 @@ splat_taskq_test1(struct file *file, void *arg)
splat_vprint(file, SPLAT_TASKQ_TEST1_NAME, splat_vprint(file, SPLAT_TASKQ_TEST1_NAME,
"Taskq '%s' function '%s' dispatching\n", "Taskq '%s' function '%s' dispatching\n",
tq_arg.name, sym2str(splat_taskq_test1_func)); tq_arg.name, sym2str(splat_taskq_test13_func));
if ((id = taskq_dispatch(tq, splat_taskq_test1_func, if ((id = taskq_dispatch(tq, splat_taskq_test13_func,
&tq_arg, TQ_SLEEP)) == 0) { &tq_arg, TQ_SLEEP)) == 0) {
splat_vprint(file, SPLAT_TASKQ_TEST1_NAME, splat_vprint(file, SPLAT_TASKQ_TEST1_NAME,
"Taskq '%s' function '%s' dispatch failed\n", "Taskq '%s' function '%s' dispatch failed\n",
tq_arg.name, sym2str(splat_taskq_test1_func)); tq_arg.name, sym2str(splat_taskq_test13_func));
taskq_destroy(tq); taskq_destroy(tq);
return -EINVAL; return -EINVAL;
} }
@ -230,6 +234,38 @@ splat_taskq_test2(struct file *file, void *arg) {
return rc; return rc;
} }
/* Validation Test 3 - Use the global system task queue with a single
* task, * wait until task completes, ensure task ran properly.
*/
static int
splat_taskq_test3(struct file *file, void *arg)
{
taskqid_t id;
splat_taskq_arg_t tq_arg;
tq_arg.flag = 0;
tq_arg.id = 0;
tq_arg.file = file;
tq_arg.name = SPLAT_TASKQ_TEST3_NAME;
splat_vprint(file, SPLAT_TASKQ_TEST3_NAME,
"Taskq '%s' function '%s' dispatching\n",
tq_arg.name, sym2str(splat_taskq_test13_func));
if ((id = taskq_dispatch(system_taskq, splat_taskq_test13_func,
&tq_arg, TQ_SLEEP)) == 0) {
splat_vprint(file, SPLAT_TASKQ_TEST3_NAME,
"Taskq '%s' function '%s' dispatch failed\n",
tq_arg.name, sym2str(splat_taskq_test13_func));
return -EINVAL;
}
splat_vprint(file, SPLAT_TASKQ_TEST3_NAME, "Taskq '%s' waiting\n",
tq_arg.name);
taskq_wait(system_taskq);
return (tq_arg.flag) ? 0 : -EINVAL;
}
splat_subsystem_t * splat_subsystem_t *
splat_taskq_init(void) splat_taskq_init(void)
{ {
@ -251,6 +287,8 @@ splat_taskq_init(void)
SPLAT_TASKQ_TEST1_ID, splat_taskq_test1); SPLAT_TASKQ_TEST1_ID, splat_taskq_test1);
SPLAT_TEST_INIT(sub, SPLAT_TASKQ_TEST2_NAME, SPLAT_TASKQ_TEST2_DESC, SPLAT_TEST_INIT(sub, SPLAT_TASKQ_TEST2_NAME, SPLAT_TASKQ_TEST2_DESC,
SPLAT_TASKQ_TEST2_ID, splat_taskq_test2); SPLAT_TASKQ_TEST2_ID, splat_taskq_test2);
SPLAT_TEST_INIT(sub, SPLAT_TASKQ_TEST3_NAME, SPLAT_TASKQ_TEST3_DESC,
SPLAT_TASKQ_TEST3_ID, splat_taskq_test3);
return sub; return sub;
} }
@ -259,6 +297,7 @@ void
splat_taskq_fini(splat_subsystem_t *sub) splat_taskq_fini(splat_subsystem_t *sub)
{ {
ASSERT(sub); ASSERT(sub);
SPLAT_TEST_FINI(sub, SPLAT_TASKQ_TEST3_ID);
SPLAT_TEST_FINI(sub, SPLAT_TASKQ_TEST2_ID); SPLAT_TEST_FINI(sub, SPLAT_TASKQ_TEST2_ID);
SPLAT_TEST_FINI(sub, SPLAT_TASKQ_TEST1_ID); SPLAT_TEST_FINI(sub, SPLAT_TASKQ_TEST1_ID);