summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound
diff options
context:
space:
mode:
authorariff <ariff@FreeBSD.org>2007-02-01 09:46:03 +0000
committerariff <ariff@FreeBSD.org>2007-02-01 09:46:03 +0000
commitef779241ba938ab74bc1fc9474db9edd393a9a1e (patch)
treeb7187e3635d9af1d354db0c62fe905109758b90c /sys/dev/sound
parentf763a443cd487389b72898bd4b6bc2f9631efa68 (diff)
downloadFreeBSD-src-ef779241ba938ab74bc1fc9474db9edd393a9a1e.zip
FreeBSD-src-ef779241ba938ab74bc1fc9474db9edd393a9a1e.tar.gz
Fix huge memory leak within sound buffer (during channel destruction,
buffer resizing, etc.) that was here since eon. Free all (unmanaged) allocated buffer through sndbuf_destroy() in case we forgot to call sndbuf_free(). For a managed buffer (mostly hw specific managed buffer), either provide CHANNEL_FREE() method with appropriate return value to invoke semi-automatic sndbuf_free() or simply do it on their own. If everything is failed, sndbuf_destroy() will come to the rescue as a final measure. MFC after: 3 days
Diffstat (limited to 'sys/dev/sound')
-rw-r--r--sys/dev/sound/pcm/buffer.c12
-rw-r--r--sys/dev/sound/pcm/buffer.h1
2 files changed, 13 insertions, 0 deletions
diff --git a/sys/dev/sound/pcm/buffer.c b/sys/dev/sound/pcm/buffer.c
index e12765e..33155d3 100644
--- a/sys/dev/sound/pcm/buffer.c
+++ b/sys/dev/sound/pcm/buffer.c
@@ -46,6 +46,12 @@ sndbuf_create(device_t dev, char *drv, char *desc, struct pcm_channel *channel)
void
sndbuf_destroy(struct snd_dbuf *b)
{
+ if (b->tmpbuf)
+ free(b->tmpbuf, M_DEVBUF);
+ if (b->shadbuf)
+ free(b->shadbuf, M_DEVBUF);
+ if (!(b->flags & SNDBUF_F_MANAGED) && b->buf)
+ free(b->buf, M_DEVBUF);
free(b, M_DEVBUF);
}
@@ -85,6 +91,7 @@ sndbuf_alloc(struct snd_dbuf *b, bus_dma_tag_t dmatag, unsigned int size)
b->maxsize = size;
b->bufsize = b->maxsize;
b->buf_addr = 0;
+ b->flags |= SNDBUF_F_MANAGED;
if (bus_dmamem_alloc(b->dmatag, (void **)&b->buf, BUS_DMA_NOWAIT,
&b->dmamap))
return (ENOMEM);
@@ -104,6 +111,8 @@ sndbuf_alloc(struct snd_dbuf *b, bus_dma_tag_t dmatag, unsigned int size)
int
sndbuf_setup(struct snd_dbuf *b, void *buf, unsigned int size)
{
+ if (buf)
+ b->flags |= SNDBUF_F_MANAGED;
b->buf = buf;
b->maxsize = size;
b->bufsize = b->maxsize;
@@ -122,6 +131,9 @@ sndbuf_free(struct snd_dbuf *b)
b->shadbuf = NULL;
b->sl = 0;
+ if (!(b->flags & SNDBUF_F_MANAGED) && b->buf)
+ free(b->buf, M_DEVBUF);
+
if (b->dmamap)
bus_dmamap_unload(b->dmatag, b->dmamap);
diff --git a/sys/dev/sound/pcm/buffer.h b/sys/dev/sound/pcm/buffer.h
index 67e08a7..25e745f 100644
--- a/sys/dev/sound/pcm/buffer.h
+++ b/sys/dev/sound/pcm/buffer.h
@@ -32,6 +32,7 @@
#define SNDBUF_F_DMA 0x00000001
#define SNDBUF_F_XRUN 0x00000002
#define SNDBUF_F_RUNNING 0x00000004
+#define SNDBUF_F_MANAGED 0x00000008
#define SNDBUF_NAMELEN 48
OpenPOWER on IntegriCloud