summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2009-09-02 14:05:06 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2009-09-02 14:05:06 +0000
commit2de40a35d82ec6b2760a45b24d358182bf34e450 (patch)
treeff175cda8b291c8a3dbb2ee39d5fa6bd1e31b50a
parent41a51176f9e0dd52dfaffaab7ad0f3f12394606c (diff)
when you add a task to a workq, it allocates memory to handle the
task and shove it on a list. allocations can fail, so if something that wants to run a task later already has memory to handle the workq task then let it provide it via a new function called workq_queue_task. ok kettenis@
-rw-r--r--sys/kern/kern_workq.c36
-rw-r--r--sys/sys/workq.h20
2 files changed, 37 insertions, 19 deletions
diff --git a/sys/kern/kern_workq.c b/sys/kern/kern_workq.c
index 6c98f35baf2..3f186e5c3e2 100644
--- a/sys/kern/kern_workq.c
+++ b/sys/kern/kern_workq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_workq.c,v 1.10 2009/06/24 14:56:41 jsg Exp $ */
+/* $OpenBSD: kern_workq.c,v 1.11 2009/09/02 14:05:05 dlg Exp $ */
/*
* Copyright (c) 2007 David Gwynne <dlg@openbsd.org>
@@ -26,15 +26,6 @@
#include <sys/kthread.h>
#include <sys/workq.h>
-struct workq_task {
- int wqt_flags;
- workq_fn wqt_func;
- void *wqt_arg1;
- void *wqt_arg2;
-
- SIMPLEQ_ENTRY(workq_task) wqt_entry;
-};
-
struct workq {
int wq_flags;
#define WQ_F_RUNNING (1<<0)
@@ -54,6 +45,9 @@ struct workq workq_syswq = {
"syswq"
};
+/* if we allocate the wqt, we need to know we free it too */
+#define WQT_F_POOL (1 << 31)
+
void workq_init(void); /* called in init_main.c */
void workq_init_syswq(void *);
void workq_create_thread(void *);
@@ -127,27 +121,34 @@ int
workq_add_task(struct workq *wq, int flags, workq_fn func, void *a1, void *a2)
{
struct workq_task *wqt;
-
- if (wq == NULL)
- wq = &workq_syswq;
wqt = pool_get(&workq_task_pool, (flags & WQ_WAITOK) ?
PR_WAITOK : PR_NOWAIT);
if (!wqt)
return (ENOMEM);
+ workq_queue_task(wq, wqt, WQT_F_POOL | flags, func, a1, a2);
+
+ return (0);
+}
+
+void
+workq_queue_task(struct workq *wq, struct workq_task *wqt, int flags,
+ workq_fn func, void *a1, void *a2)
+{
wqt->wqt_flags = flags;
wqt->wqt_func = func;
wqt->wqt_arg1 = a1;
wqt->wqt_arg2 = a2;
+ if (wq == NULL)
+ wq = &workq_syswq;
+
mtx_enter(&wq->wq_mtx);
SIMPLEQ_INSERT_TAIL(&wq->wq_tasklist, wqt, wqt_entry);
mtx_leave(&wq->wq_mtx);
wakeup_one(wq);
-
- return (0);
}
void
@@ -202,10 +203,13 @@ workq_thread(void *arg)
{
struct workq *wq = arg;
struct workq_task *wqt;
+ int mypool;
while ((wqt = workq_next_task(wq)) != NULL) {
+ mypool = (wqt->wqt_flags & WQT_F_POOL);
wqt->wqt_func(wqt->wqt_arg1, wqt->wqt_arg2);
- pool_put(&workq_task_pool, wqt);
+ if (mypool)
+ pool_put(&workq_task_pool, wqt);
}
kthread_exit(0);
diff --git a/sys/sys/workq.h b/sys/sys/workq.h
index 728dc64e6a4..dc7289a5af8 100644
--- a/sys/sys/workq.h
+++ b/sys/sys/workq.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: workq.h,v 1.5 2008/10/30 23:55:22 dlg Exp $ */
+/* $OpenBSD: workq.h,v 1.6 2009/09/02 14:05:05 dlg Exp $ */
/*
* Copyright (c) 2007 David Gwynne <dlg@openbsd.org>
@@ -20,15 +20,29 @@
#ifndef _SYS_WORKQ_H_
#define _SYS_WORKQ_H_
-struct workq;
+#include <sys/queue.h>
+
+typedef void (*workq_fn)(void *, void *);
+
+struct workq_task {
+ int wqt_flags;
+ workq_fn wqt_func;
+ void *wqt_arg1;
+ void *wqt_arg2;
+
+ SIMPLEQ_ENTRY(workq_task) wqt_entry;
+};
#define WQ_WAITOK (1<<0)
#define WQ_MPSAFE (1<<1)
-typedef void (*workq_fn)(void *, void *);
+struct workq;
+
struct workq *workq_create(const char *, int, int);
int workq_add_task(struct workq *, int /* flags */, workq_fn,
void *, void *);
+void workq_queue_task(struct workq *, struct workq_task *,
+ int /* flags */, workq_fn, void *, void *);
void workq_destroy(struct workq *);
#endif /* _SYS_WORKQ_H_ */