From 5a5410b87d10f14ce9d6c1ae2e8093fc737d7371 Mon Sep 17 00:00:00 2001 From: Simon Schubert Date: Sat, 5 Jan 2008 13:34:22 +0000 Subject: [PATCH] Call selwakeup() from an MP-protected taskqueue. Before, we would call selwakeup() from interrupt context. This was working as long kern.intr_mpsafe == 0. selwakeup() however needs the MP lock held, so we can't call it directly from the interrupt when running with kern.intr_mpsafe=1. Instead, perform the wakeup from a "bottom half" taskqueue SWI to make the sound devices intr_mpsafe, as they claim to be. --- sys/dev/sound/pcm/buffer.c | 21 +++++++++++++++++++-- sys/dev/sound/pcm/buffer.h | 3 ++- sys/dev/sound/pcm/channel.c | 20 ++++++++++++++++---- sys/dev/sound/pcm/sound.h | 3 ++- 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/sys/dev/sound/pcm/buffer.c b/sys/dev/sound/pcm/buffer.c index 71ca492b9e..0bf4522a96 100644 --- a/sys/dev/sound/pcm/buffer.c +++ b/sys/dev/sound/pcm/buffer.c @@ -24,14 +24,30 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/dev/sound/pcm/buffer.c,v 1.25.2.3 2007/04/26 08:21:43 ariff Exp $ - * $DragonFly: src/sys/dev/sound/pcm/buffer.c,v 1.9 2007/06/16 19:48:05 hasso Exp $ + * $DragonFly: src/sys/dev/sound/pcm/buffer.c,v 1.10 2008/01/05 13:34:22 corecode Exp $ */ #include #include "feeder_if.h" -SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pcm/buffer.c,v 1.9 2007/06/16 19:48:05 hasso Exp $"); +SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pcm/buffer.c,v 1.10 2008/01/05 13:34:22 corecode Exp $"); + +/* + * sndbuf_seltask is a taskqueue callback routine, called from + * taskqueue_swi, which runs under the MP lock. + * + * The only purpose is to be able to selwakeup() from a sound + * interrupt, which is running without MP lock held and thus + * can't call selwakeup() directly. + */ +static void +sndbuf_seltask(void *context, int pending) +{ + struct snd_dbuf *b = context; + + selwakeup(sndbuf_getsel(b)); +} struct snd_dbuf * sndbuf_create(device_t dev, char *drv, char *desc, struct pcm_channel *channel) @@ -42,6 +58,7 @@ sndbuf_create(device_t dev, char *drv, char *desc, struct pcm_channel *channel) ksnprintf(b->name, SNDBUF_NAMELEN, "%s:%s", drv, desc); b->dev = dev; b->channel = channel; + TASK_INIT(&b->seltask, 0, sndbuf_seltask, b); return b; } diff --git a/sys/dev/sound/pcm/buffer.h b/sys/dev/sound/pcm/buffer.h index 89458faae4..dd0e62460d 100644 --- a/sys/dev/sound/pcm/buffer.h +++ b/sys/dev/sound/pcm/buffer.h @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/dev/sound/pcm/buffer.h,v 1.10.2.2 2007/05/13 20:50:31 ariff Exp $ - * $DragonFly: src/sys/dev/sound/pcm/buffer.h,v 1.4 2007/06/16 19:48:05 hasso Exp $ + * $DragonFly: src/sys/dev/sound/pcm/buffer.h,v 1.5 2008/01/05 13:34:22 corecode Exp $ */ #define SND_DMA(b) (sndbuf_getflags((b)) & SNDBUF_F_DMA) @@ -55,6 +55,7 @@ struct snd_dbuf { bus_dma_tag_t dmatag; bus_addr_t buf_addr; struct selinfo sel; + struct task seltask; struct pcm_channel *channel; char name[SNDBUF_NAMELEN]; }; diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c index 415af37c46..68460d7545 100644 --- a/sys/dev/sound/pcm/channel.c +++ b/sys/dev/sound/pcm/channel.c @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/dev/sound/pcm/channel.c,v 1.99.2.5 2007/05/13 20:53:39 ariff Exp $ - * $DragonFly: src/sys/dev/sound/pcm/channel.c,v 1.14 2007/06/16 20:07:22 dillon Exp $ + * $DragonFly: src/sys/dev/sound/pcm/channel.c,v 1.15 2008/01/05 13:34:22 corecode Exp $ */ #include "use_isa.h" @@ -35,7 +35,7 @@ #include "feeder_if.h" -SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pcm/channel.c,v 1.14 2007/06/16 20:07:22 dillon Exp $"); +SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pcm/channel.c,v 1.15 2008/01/05 13:34:22 corecode Exp $"); #define MIN_CHUNK_SIZE 256 /* for uiomove etc. */ #if 0 @@ -141,8 +141,20 @@ chn_wakeup(struct pcm_channel *c) CHN_LOCKASSERT(c); if (SLIST_EMPTY(&c->children)) { /*if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c))*/ - if (sndbuf_getsel(bs)->si_pid && chn_polltrigger(c)) - selwakeup(sndbuf_getsel(bs)); + if (sndbuf_getsel(bs)->si_pid && chn_polltrigger(c)) { + /* + * We would call selwakeup() here, but as we + * are in interrupt context, we'd have to + * aquire the MP lock before. + * Instead, we'll queue a task in a software + * interrupt, which will run with the MP lock + * held. + * + * buffer.c:sndbuf_seltask will then call + * selwakeup() from safer context. + */ + taskqueue_enqueue(taskqueue_swi, &bs->seltask); + } } else { SLIST_FOREACH(pce, &c->children, link) { CHN_LOCK(pce->channel); diff --git a/sys/dev/sound/pcm/sound.h b/sys/dev/sound/pcm/sound.h index 20be4414a3..a58e96ed76 100644 --- a/sys/dev/sound/pcm/sound.h +++ b/sys/dev/sound/pcm/sound.h @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/dev/sound/pcm/sound.h,v 1.63.2.3 2007/05/13 20:53:39 ariff Exp $ - * $DragonFly: src/sys/dev/sound/pcm/sound.h,v 1.13 2007/06/16 20:07:22 dillon Exp $ + * $DragonFly: src/sys/dev/sound/pcm/sound.h,v 1.14 2008/01/05 13:34:22 corecode Exp $ */ /* @@ -65,6 +65,7 @@ #include #include #include +#include #include /* for DELAY */ -- 2.41.0