summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2015-02-09 03:15:42 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2015-02-09 03:15:42 +0000
commit24ad848078fcf32ba92421894c27fa8abb452209 (patch)
tree310b78e8bbf34ba1ceab66cfc2bd1afacecde97b /sys
parentb0353336ff6ce726e4e5366de313c7cbf62de3c1 (diff)
we want to defer work traditionally (in openbsd) handled in an
interrupt context to a taskq running in a thread. however, there is a concern that if we do that then we allow accidental use of sleeping APIs in this work, which will make it harder to move the work back to interrupts in the future. guenther and kettenis came up with the idea of marking a proc with CANTSLEEP which the sleep paths can check and panic on. this builds on that so you create taskqs that run with CANTSLEEP set except when they need to sleep for more tasks to run. the taskq_create api is changed to take a flags argument so users can specify CANTSLEEP. MPSAFE is also passed via this flags field now. this means archs that defined IPL_MPSAFE to 0 can now create mpsafe taskqs too. lots of discussion at s2k15 ok guenther@ miod@ mpi@ tedu@ pelikan@
Diffstat (limited to 'sys')
-rw-r--r--sys/crypto/crypto.c4
-rw-r--r--sys/dev/ic/qla.c4
-rw-r--r--sys/dev/pci/drm/i915/i915_drv.c4
-rw-r--r--sys/dev/pci/drm/ttm/ttm_memory.c4
-rw-r--r--sys/dev/pci/qle.c4
-rw-r--r--sys/dev/pci/viomb.c4
-rw-r--r--sys/dev/softraid.c4
-rw-r--r--sys/kern/kern_sensors.c4
-rw-r--r--sys/kern/kern_synch.c4
-rw-r--r--sys/kern/kern_task.c62
-rw-r--r--sys/sys/proc.h6
-rw-r--r--sys/sys/task.h7
12 files changed, 74 insertions, 37 deletions
diff --git a/sys/crypto/crypto.c b/sys/crypto/crypto.c
index 88c6ec51960..8ab5563e9a9 100644
--- a/sys/crypto/crypto.c
+++ b/sys/crypto/crypto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: crypto.c,v 1.73 2015/01/27 03:17:35 dlg Exp $ */
+/* $OpenBSD: crypto.c,v 1.74 2015/02/09 03:15:41 dlg Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
*
@@ -495,7 +495,7 @@ crypto_getreq(int num)
void
crypto_init(void)
{
- crypto_taskq = taskq_create("crypto", 1, IPL_VM);
+ crypto_taskq = taskq_create("crypto", 1, IPL_VM, 0);
pool_init(&cryptop_pool, sizeof(struct cryptop), 0, 0,
0, "cryptop", NULL);
diff --git a/sys/dev/ic/qla.c b/sys/dev/ic/qla.c
index e603d891f66..1552f330ae0 100644
--- a/sys/dev/ic/qla.c
+++ b/sys/dev/ic/qla.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: qla.c,v 1.47 2015/01/27 03:17:36 dlg Exp $ */
+/* $OpenBSD: qla.c,v 1.48 2015/02/09 03:15:41 dlg Exp $ */
/*
* Copyright (c) 2011 David Gwynne <dlg@openbsd.org>
@@ -648,7 +648,7 @@ qla_attach(struct qla_softc *sc)
goto free_scratch;
}
- sc->sc_update_taskq = taskq_create(DEVNAME(sc), 1, IPL_BIO);
+ sc->sc_update_taskq = taskq_create(DEVNAME(sc), 1, IPL_BIO, 0);
task_set(&sc->sc_update_task, qla_do_update, sc);
/* wait a bit for link to come up so we can scan and attach devices */
diff --git a/sys/dev/pci/drm/i915/i915_drv.c b/sys/dev/pci/drm/i915/i915_drv.c
index b8bec4b413a..c1b0c1a0eaf 100644
--- a/sys/dev/pci/drm/i915/i915_drv.c
+++ b/sys/dev/pci/drm/i915/i915_drv.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: i915_drv.c,v 1.70 2015/01/27 03:17:36 dlg Exp $ */
+/* $OpenBSD: i915_drv.c,v 1.71 2015/02/09 03:15:41 dlg Exp $ */
/*
* Copyright (c) 2008-2009 Owain G. Ainsworth <oga@openbsd.org>
*
@@ -940,7 +940,7 @@ inteldrm_attach(struct device *parent, struct device *self, void *aux)
return;
}
- dev_priv->mm.retire_taskq = taskq_create("intelrel", 1, IPL_TTY);
+ dev_priv->mm.retire_taskq = taskq_create("intelrel", 1, IPL_TTY, 0);
if (dev_priv->mm.retire_taskq == NULL) {
printf("couldn't create taskq\n");
return;
diff --git a/sys/dev/pci/drm/ttm/ttm_memory.c b/sys/dev/pci/drm/ttm/ttm_memory.c
index e12af2b2a4a..8f2c38ca8c9 100644
--- a/sys/dev/pci/drm/ttm/ttm_memory.c
+++ b/sys/dev/pci/drm/ttm/ttm_memory.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ttm_memory.c,v 1.5 2015/01/27 03:17:36 dlg Exp $ */
+/* $OpenBSD: ttm_memory.c,v 1.6 2015/02/09 03:15:41 dlg Exp $ */
/**************************************************************************
*
* Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
@@ -336,7 +336,7 @@ int ttm_mem_global_init(struct ttm_mem_global *glob)
#endif
mtx_init(&glob->lock, IPL_TTY);
- glob->swap_queue = taskq_create("ttm_swap", 1, IPL_TTY);
+ glob->swap_queue = taskq_create("ttm_swap", 1, IPL_TTY, 0);
glob->task_queued = false;
task_set(&glob->task, ttm_shrink_work, glob);
diff --git a/sys/dev/pci/qle.c b/sys/dev/pci/qle.c
index dfebf899200..71019cb03e1 100644
--- a/sys/dev/pci/qle.c
+++ b/sys/dev/pci/qle.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: qle.c,v 1.33 2015/01/27 03:17:36 dlg Exp $ */
+/* $OpenBSD: qle.c,v 1.34 2015/02/09 03:15:41 dlg Exp $ */
/*
* Copyright (c) 2013, 2014 Jonathan Matthew <jmatthew@openbsd.org>
@@ -625,7 +625,7 @@ qle_attach(struct device *parent, struct device *self, void *aux)
goto free_scratch;
}
- sc->sc_update_taskq = taskq_create(DEVNAME(sc), 1, IPL_BIO);
+ sc->sc_update_taskq = taskq_create(DEVNAME(sc), 1, IPL_BIO, 0);
task_set(&sc->sc_update_task, qle_do_update, sc);
/* wait a bit for link to come up so we can scan and attach devices */
diff --git a/sys/dev/pci/viomb.c b/sys/dev/pci/viomb.c
index 60cbd61c44d..bb06915a17c 100644
--- a/sys/dev/pci/viomb.c
+++ b/sys/dev/pci/viomb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: viomb.c,v 1.11 2015/01/27 03:17:36 dlg Exp $ */
+/* $OpenBSD: viomb.c,v 1.12 2015/02/09 03:15:41 dlg Exp $ */
/* $NetBSD: viomb.c,v 1.1 2011/10/30 12:12:21 hannken Exp $ */
/*
@@ -202,7 +202,7 @@ viomb_attach(struct device *parent, struct device *self, void *aux)
goto err_dmamap;
}
- sc->sc_taskq = taskq_create("viomb", 1, IPL_BIO);
+ sc->sc_taskq = taskq_create("viomb", 1, IPL_BIO, 0);
if (sc->sc_taskq == NULL)
goto err_dmamap;
task_set(&sc->sc_task, viomb_worker, sc);
diff --git a/sys/dev/softraid.c b/sys/dev/softraid.c
index b9f6643243b..9dee6c5d64a 100644
--- a/sys/dev/softraid.c
+++ b/sys/dev/softraid.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraid.c,v 1.348 2015/01/27 03:17:35 dlg Exp $ */
+/* $OpenBSD: softraid.c,v 1.349 2015/02/09 03:15:41 dlg Exp $ */
/*
* Copyright (c) 2007, 2008, 2009 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2008 Chris Kuethe <ckuethe@openbsd.org>
@@ -3297,7 +3297,7 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc,
sd = malloc(sizeof(struct sr_discipline), M_DEVBUF, M_WAITOK | M_ZERO);
sd->sd_sc = sc;
SLIST_INIT(&sd->sd_meta_opt);
- sd->sd_taskq = taskq_create("srdis", 1, IPL_BIO);
+ sd->sd_taskq = taskq_create("srdis", 1, IPL_BIO, 0);
if (sd->sd_taskq == NULL) {
sr_error(sc, "could not create discipline taskq");
goto unwind;
diff --git a/sys/kern/kern_sensors.c b/sys/kern/kern_sensors.c
index e9bddd8d8a8..332fb6103fc 100644
--- a/sys/kern/kern_sensors.c
+++ b/sys/kern/kern_sensors.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sensors.c,v 1.34 2015/01/27 03:17:36 dlg Exp $ */
+/* $OpenBSD: kern_sensors.c,v 1.35 2015/02/09 03:15:41 dlg Exp $ */
/*
* Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
@@ -193,7 +193,7 @@ sensor_task_register(void *arg, void (*func)(void *), unsigned int period)
#endif
if (sensors_taskq == NULL &&
- (sensors_taskq = taskq_create("sensors", 1, IPL_HIGH)) == NULL)
+ (sensors_taskq = taskq_create("sensors", 1, IPL_HIGH, 0)) == NULL)
sensors_taskq = systq;
st = malloc(sizeof(*st), M_DEVBUF, M_NOWAIT);
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c
index fbf768457d5..9f8eff7e5f8 100644
--- a/sys/kern/kern_synch.c
+++ b/sys/kern/kern_synch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_synch.c,v 1.116 2014/07/08 17:19:25 deraadt Exp $ */
+/* $OpenBSD: kern_synch.c,v 1.117 2015/02/09 03:15:41 dlg Exp $ */
/* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */
/*
@@ -191,6 +191,8 @@ sleep_setup(struct sleep_state *sls, const volatile void *ident, int prio,
struct proc *p = curproc;
#ifdef DIAGNOSTIC
+ if (p->p_flag & P_CANTSLEEP)
+ panic("sleep: %s failed insomnia", p->p_comm);
if (ident == NULL)
panic("tsleep: no ident");
if (p->p_stat != SONPROC)
diff --git a/sys/kern/kern_task.c b/sys/kern/kern_task.c
index b0b6457509e..8c736bd9679 100644
--- a/sys/kern/kern_task.c
+++ b/sys/kern/kern_task.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_task.c,v 1.13 2015/01/27 03:17:36 dlg Exp $ */
+/* $OpenBSD: kern_task.c,v 1.14 2015/02/09 03:15:41 dlg Exp $ */
/*
* Copyright (c) 2013 David Gwynne <dlg@openbsd.org>
@@ -33,7 +33,7 @@ struct taskq {
} tq_state;
unsigned int tq_running;
unsigned int tq_nthreads;
- unsigned int tq_unlocked;
+ unsigned int tq_flags;
const char *tq_name;
struct mutex tq_mtx;
@@ -54,18 +54,23 @@ struct taskq taskq_sys_mp = {
TQ_S_CREATED,
0,
1,
- 1,
+ TASKQ_MPSAFE,
"systqmp",
MUTEX_INITIALIZER(IPL_HIGH),
TAILQ_HEAD_INITIALIZER(taskq_sys_mp.tq_worklist)
};
+typedef int (*sleepfn)(const volatile void *, struct mutex *, int,
+ const char *, int);
+
struct taskq *const systq = &taskq_sys;
struct taskq *const systqmp = &taskq_sys_mp;
void taskq_init(void); /* called in init_main.c */
void taskq_create_thread(void *);
-int taskq_next_work(struct taskq *, struct task *);
+int taskq_sleep(const volatile void *, struct mutex *, int,
+ const char *, int);
+int taskq_next_work(struct taskq *, struct task *, sleepfn);
void taskq_thread(void *);
void
@@ -76,7 +81,8 @@ taskq_init(void)
}
struct taskq *
-taskq_create(const char *name, unsigned int nthreads, int ipl)
+taskq_create(const char *name, unsigned int nthreads, int ipl,
+ unsigned int flags)
{
struct taskq *tq;
@@ -88,12 +94,7 @@ taskq_create(const char *name, unsigned int nthreads, int ipl)
tq->tq_running = 0;
tq->tq_nthreads = nthreads;
tq->tq_name = name;
-
- if (ipl & IPL_MPSAFE)
- tq->tq_unlocked = 1;
- else
- tq->tq_unlocked = 0;
- ipl &= ~IPL_MPSAFE;
+ tq->tq_flags = flags;
mtx_init(&tq->tq_mtx, ipl);
TAILQ_INIT(&tq->tq_worklist);
@@ -190,6 +191,9 @@ task_add(struct taskq *tq, struct task *w)
{
int rv = 0;
+ if (ISSET(w->t_flags, TASK_ONQUEUE))
+ return (0);
+
mtx_enter(&tq->tq_mtx);
if (!ISSET(w->t_flags, TASK_ONQUEUE)) {
rv = 1;
@@ -209,6 +213,9 @@ task_del(struct taskq *tq, struct task *w)
{
int rv = 0;
+ if (!ISSET(w->t_flags, TASK_ONQUEUE))
+ return (0);
+
mtx_enter(&tq->tq_mtx);
if (ISSET(w->t_flags, TASK_ONQUEUE)) {
rv = 1;
@@ -221,7 +228,21 @@ task_del(struct taskq *tq, struct task *w)
}
int
-taskq_next_work(struct taskq *tq, struct task *work)
+taskq_sleep(const volatile void *ident, struct mutex *mtx, int priority,
+ const char *wmesg, int tmo)
+{
+ u_int *flags = &curproc->p_flag;
+ int rv;
+
+ atomic_clearbits_int(flags, P_CANTSLEEP);
+ rv = msleep(ident, mtx, priority, wmesg, tmo);
+ atomic_setbits_int(flags, P_CANTSLEEP);
+
+ return (tmo);
+}
+
+int
+taskq_next_work(struct taskq *tq, struct task *work, sleepfn tqsleep)
{
struct task *next;
@@ -232,7 +253,7 @@ taskq_next_work(struct taskq *tq, struct task *work)
return (0);
}
- msleep(tq, &tq->tq_mtx, PWAIT, "bored", 0);
+ tqsleep(tq, &tq->tq_mtx, PWAIT, "bored", 0);
}
TAILQ_REMOVE(&tq->tq_worklist, next, t_entry);
@@ -252,14 +273,20 @@ taskq_next_work(struct taskq *tq, struct task *work)
void
taskq_thread(void *xtq)
{
+ sleepfn tqsleep = msleep;
struct taskq *tq = xtq;
struct task work;
int last;
- if (tq->tq_unlocked)
+ if (ISSET(tq->tq_flags, TASKQ_MPSAFE))
KERNEL_UNLOCK();
- while (taskq_next_work(tq, &work)) {
+ if (ISSET(tq->tq_flags, TASKQ_CANTSLEEP)) {
+ tqsleep = taskq_sleep;
+ atomic_setbits_int(&curproc->p_flag, P_CANTSLEEP);
+ }
+
+ while (taskq_next_work(tq, &work, tqsleep)) {
(*work.t_func)(work.t_arg);
sched_pause();
}
@@ -268,9 +295,12 @@ taskq_thread(void *xtq)
last = (--tq->tq_running == 0);
mtx_leave(&tq->tq_mtx);
- if (tq->tq_unlocked)
+ if (ISSET(tq->tq_flags, TASKQ_MPSAFE))
KERNEL_LOCK();
+ if (ISSET(tq->tq_flags, TASKQ_CANTSLEEP))
+ atomic_clearbits_int(&curproc->p_flag, P_CANTSLEEP);
+
if (last)
wakeup_one(&tq->tq_running);
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index f00a9f8d48b..8409c435fe8 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: proc.h,v 1.194 2015/01/26 22:51:37 kettenis Exp $ */
+/* $OpenBSD: proc.h,v 1.195 2015/02/09 03:15:41 dlg Exp $ */
/* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */
/*-
@@ -364,6 +364,8 @@ struct proc {
#define P_PROFPEND 0x000002 /* SIGPROF needs to be posted */
#define P_ALRMPEND 0x000004 /* SIGVTALRM needs to be posted */
#define P_SIGSUSPEND 0x000008 /* Need to restore before-suspend mask*/
+
+#define P_CANTSLEEP 0x000010 /* insomniac thread */
#define P_SELECT 0x000040 /* Selecting; wakeup/waiting danger. */
#define P_SINTR 0x000080 /* Sleep is interruptible. */
#define P_SYSTEM 0x000200 /* No sigs, stats or swapping. */
@@ -379,7 +381,7 @@ struct proc {
#define P_CPUPEG 0x40000000 /* Do not move to another cpu. */
#define P_BITS \
- ("\20\01INKTR\02PROFPEND\03ALRMPEND\04SIGSUSPEND\07SELECT" \
+ ("\20\01INKTR\02PROFPEND\03ALRMPEND\04SIGSUSPEND\05CANTSLEEP\07SELECT" \
"\010SINTR\012SYSTEM" \
"\013TIMEOUT\016WEXIT\020OWEUPC\024SUSPSINGLE" \
"\027SYSTRACE\030CONTINUED\033THREAD" \
diff --git a/sys/sys/task.h b/sys/sys/task.h
index 9eef0adc019..e37099e5639 100644
--- a/sys/sys/task.h
+++ b/sys/sys/task.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: task.h,v 1.7 2015/01/27 03:17:37 dlg Exp $ */
+/* $OpenBSD: task.h,v 1.8 2015/02/09 03:15:41 dlg Exp $ */
/*
* Copyright (c) 2013 David Gwynne <dlg@openbsd.org>
@@ -30,11 +30,14 @@ struct task {
unsigned int t_flags;
};
+#define TASKQ_MPSAFE (1 << 0)
+#define TASKQ_CANTSLEEP (1 << 1)
+
#ifdef _KERNEL
extern struct taskq *const systq;
extern struct taskq *const systqmp;
-struct taskq *taskq_create(const char *, unsigned int, int);
+struct taskq *taskq_create(const char *, unsigned int, int, unsigned int);
void taskq_destroy(struct taskq *);
void task_set(struct task *, void (*)(void *), void *);