summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_workq.c
diff options
context:
space:
mode:
authordlg <dlg@openbsd.org>2009-09-02 14:05:05 +0000
committerdlg <dlg@openbsd.org>2009-09-02 14:05:05 +0000
commit71472cd3c98f2101fe178d61943dc8a271eafbf1 (patch)
tree884f5d428a85793229eac745ff03cb04e2b5fb4e /sys/kern/kern_workq.c
parentall the new *-to options are part of the "filteropts" section at the (diff)
downloadwireguard-openbsd-71472cd3c98f2101fe178d61943dc8a271eafbf1.tar.xz
wireguard-openbsd-71472cd3c98f2101fe178d61943dc8a271eafbf1.zip
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@
Diffstat (limited to 'sys/kern/kern_workq.c')
-rw-r--r--sys/kern/kern_workq.c36
1 files changed, 20 insertions, 16 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);