diff options
author | ariff <ariff@FreeBSD.org> | 2007-02-01 09:46:03 +0000 |
---|---|---|
committer | ariff <ariff@FreeBSD.org> | 2007-02-01 09:46:03 +0000 |
commit | ef779241ba938ab74bc1fc9474db9edd393a9a1e (patch) | |
tree | b7187e3635d9af1d354db0c62fe905109758b90c /sys/dev/sound | |
parent | f763a443cd487389b72898bd4b6bc2f9631efa68 (diff) | |
download | FreeBSD-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.c | 12 | ||||
-rw-r--r-- | sys/dev/sound/pcm/buffer.h | 1 |
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 |