]>
Commit | Line | Data |
---|---|---|
f4b37741 | 1 | #include <sys/taskq.h> |
f1ca4da6 | 2 | |
937879f1 BB |
3 | #ifdef DEBUG_SUBSYSTEM |
4 | #undef DEBUG_SUBSYSTEM | |
5 | #endif | |
6 | ||
7 | #define DEBUG_SUBSYSTEM S_TASKQ | |
8 | ||
f1ca4da6 BB |
9 | /* |
10 | * Task queue interface | |
11 | * | |
12 | * The taskq_work_wrapper functions are used to manage the work_structs | |
13 | * which must be submitted to linux. The shim layer allocates a wrapper | |
14 | * structure for all items which contains a pointer to itself as well as | |
15 | * the real work to be performed. When the work item run the generic | |
16 | * handle is called which calls the real work function and then using | |
17 | * the self pointer frees the work_struct. | |
18 | */ | |
19 | typedef struct taskq_work_wrapper { | |
20 | struct work_struct tww_work; | |
21 | task_func_t tww_func; | |
22 | void * tww_priv; | |
23 | } taskq_work_wrapper_t; | |
24 | ||
25 | static void | |
26 | taskq_work_handler(void *priv) | |
27 | { | |
28 | taskq_work_wrapper_t *tww = priv; | |
29 | ||
937879f1 BB |
30 | ASSERT(tww); |
31 | ASSERT(tww->tww_func); | |
f1ca4da6 BB |
32 | |
33 | /* Call the real function and free the wrapper */ | |
34 | tww->tww_func(tww->tww_priv); | |
35 | kfree(tww); | |
36 | } | |
37 | ||
38 | /* XXX - All flags currently ignored */ | |
39 | taskqid_t | |
40 | __taskq_dispatch(taskq_t *tq, task_func_t func, void *priv, uint_t flags) | |
41 | { | |
42 | struct workqueue_struct *wq = tq; | |
43 | taskq_work_wrapper_t *tww; | |
44 | int rc; | |
937879f1 | 45 | ENTRY; |
f1ca4da6 | 46 | |
937879f1 BB |
47 | ASSERT(tq); |
48 | ASSERT(func); | |
f1ca4da6 | 49 | |
0a6fd143 BB |
50 | /* Use GFP_ATOMIC since this may be called in interrupt context */ |
51 | tww = (taskq_work_wrapper_t *)kmalloc(sizeof(*tww), GFP_ATOMIC); | |
f1ca4da6 | 52 | if (!tww) |
937879f1 | 53 | RETURN((taskqid_t)0); |
f1ca4da6 BB |
54 | |
55 | INIT_WORK(&(tww->tww_work), taskq_work_handler, tww); | |
56 | tww->tww_func = func; | |
57 | tww->tww_priv = priv; | |
58 | ||
59 | rc = queue_work(wq, &(tww->tww_work)); | |
60 | if (!rc) { | |
61 | kfree(tww); | |
937879f1 | 62 | RETURN((taskqid_t)0); |
f1ca4da6 BB |
63 | } |
64 | ||
937879f1 | 65 | RETURN((taskqid_t)wq); |
f1ca4da6 | 66 | } |
f1b59d26 | 67 | EXPORT_SYMBOL(__taskq_dispatch); |
f1ca4da6 BB |
68 | |
69 | /* XXX - Most args ignored until we decide if it's worth the effort | |
70 | * to emulate the solaris notion of dynamic thread pools. For | |
71 | * now we simply serialize everything through one thread which | |
72 | * may come back to bite us as a performance issue. | |
73 | * pri - Ignore priority | |
74 | * min - Ignored until this is a dynamic thread pool | |
75 | * max - Ignored until this is a dynamic thread pool | |
76 | * flags - Ignored until this is a dynamic thread_pool | |
77 | */ | |
78 | taskq_t * | |
79 | __taskq_create(const char *name, int nthreads, pri_t pri, | |
80 | int minalloc, int maxalloc, uint_t flags) | |
81 | { | |
f1b59d26 | 82 | /* NOTE: Linux workqueue names are limited to 10 chars */ |
937879f1 BB |
83 | ENTRY; |
84 | RETURN(create_singlethread_workqueue(name)); | |
f1ca4da6 | 85 | } |
f1b59d26 | 86 | EXPORT_SYMBOL(__taskq_create); |
b123971f BB |
87 | |
88 | void | |
89 | __taskq_destroy(taskq_t *tq) | |
90 | { | |
937879f1 | 91 | ENTRY; |
b123971f | 92 | destroy_workqueue(tq); |
937879f1 | 93 | EXIT; |
b123971f BB |
94 | } |
95 | EXPORT_SYMBOL(__taskq_destroy); | |
96 | ||
97 | void | |
98 | __taskq_wait(taskq_t *tq) | |
99 | { | |
937879f1 | 100 | ENTRY; |
b123971f | 101 | flush_workqueue(tq); |
937879f1 | 102 | EXIT; |
b123971f BB |
103 | } |
104 | EXPORT_SYMBOL(__taskq_wait); |