From b43d30ed2c855e05b02ead131136784ad708491e Mon Sep 17 00:00:00 2001 From: ariff Date: Thu, 14 Jun 2007 11:15:51 +0000 Subject: Buffer optimization and locking cleanup. Don't resize/malloc unless it is really necessary to ease down unlock/lock sequence. --- sys/dev/sound/pcm/buffer.c | 101 +++++++++++++++++++++++++++------------------ sys/dev/sound/pcm/buffer.h | 3 +- 2 files changed, 62 insertions(+), 42 deletions(-) diff --git a/sys/dev/sound/pcm/buffer.c b/sys/dev/sound/pcm/buffer.c index 3d10357..ad252d0 100644 --- a/sys/dev/sound/pcm/buffer.c +++ b/sys/dev/sound/pcm/buffer.c @@ -146,10 +146,13 @@ sndbuf_free(struct snd_dbuf *b) b->dmamap = NULL; } +#define SNDBUF_CACHE_SHIFT 5 + int sndbuf_resize(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz) { - u_int8_t *tmpbuf, *f2; + unsigned int bufsize, allocsize; + u_int8_t *tmpbuf; chn_lock(b->channel); if (b->maxsize == 0) @@ -158,27 +161,38 @@ sndbuf_resize(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz) blkcnt = b->blkcnt; if (blksz == 0) blksz = b->blksz; - if (blkcnt < 2 || blksz < 16 || (blkcnt * blksz > b->maxsize)) { + if (blkcnt < 2 || blksz < 16 || (blkcnt * blksz) > b->maxsize) { chn_unlock(b->channel); return EINVAL; } if (blkcnt == b->blkcnt && blksz == b->blksz) goto out; - chn_unlock(b->channel); - tmpbuf = malloc(blkcnt * blksz, M_DEVBUF, M_NOWAIT); - if (tmpbuf == NULL) - return ENOMEM; - chn_lock(b->channel); + bufsize = blkcnt * blksz; + + if (b->tmpbuf == NULL || bufsize > b->allocsize || + bufsize < (b->allocsize >> SNDBUF_CACHE_SHIFT)) { + allocsize = round_page(bufsize); + chn_unlock(b->channel); + tmpbuf = malloc(allocsize, M_DEVBUF, M_WAITOK); + chn_lock(b->channel); + if (snd_verbose > 3) + printf("%s(): b=%p %p -> %p [%d -> %d : %d]\n", + __func__, b, b->tmpbuf, tmpbuf, + b->allocsize, allocsize, bufsize); + if (b->tmpbuf != NULL) + free(b->tmpbuf, M_DEVBUF); + b->tmpbuf = tmpbuf; + b->allocsize = allocsize; + } else if (snd_verbose > 3) + printf("%s(): b=%p %d [%d] NOCHANGE\n", + __func__, b, b->allocsize, b->bufsize); + b->blkcnt = blkcnt; b->blksz = blksz; - b->bufsize = blkcnt * blksz; - f2 = b->tmpbuf; - b->tmpbuf = tmpbuf; + b->bufsize = bufsize; + sndbuf_reset(b); - chn_unlock(b->channel); - free(f2, M_DEVBUF); - return 0; out: chn_unlock(b->channel); return 0; @@ -187,49 +201,48 @@ out: int sndbuf_remalloc(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz) { - u_int8_t *buf, *tmpbuf, *f1, *f2; - u_int8_t *shadbuf, *f3; - unsigned int bufsize; - int ret; + unsigned int bufsize, allocsize; + u_int8_t *buf, *tmpbuf, *shadbuf; if (blkcnt < 2 || blksz < 16) return EINVAL; bufsize = blksz * blkcnt; - chn_unlock(b->channel); - buf = malloc(bufsize, M_DEVBUF, M_WAITOK); - tmpbuf = malloc(bufsize, M_DEVBUF, M_WAITOK); - shadbuf = malloc(bufsize, M_DEVBUF, M_WAITOK); - - chn_lock(b->channel); + if (bufsize > b->allocsize || + bufsize < (b->allocsize >> SNDBUF_CACHE_SHIFT)) { + allocsize = round_page(bufsize); + chn_unlock(b->channel); + buf = malloc(allocsize, M_DEVBUF, M_WAITOK); + tmpbuf = malloc(allocsize, M_DEVBUF, M_WAITOK); + shadbuf = malloc(allocsize, M_DEVBUF, M_WAITOK); + chn_lock(b->channel); + if (b->buf != NULL) + free(b->buf, M_DEVBUF); + b->buf = buf; + if (b->tmpbuf != NULL) + free(b->tmpbuf, M_DEVBUF); + b->tmpbuf = tmpbuf; + if (b->shadbuf != NULL) + free(b->shadbuf, M_DEVBUF); + b->shadbuf = shadbuf; + if (snd_verbose > 3) + printf("%s(): b=%p %d -> %d [%d]\n", + __func__, b, b->allocsize, allocsize, bufsize); + b->allocsize = allocsize; + } else if (snd_verbose > 3) + printf("%s(): b=%p %d [%d] NOCHANGE\n", + __func__, b, b->allocsize, b->bufsize); b->blkcnt = blkcnt; b->blksz = blksz; b->bufsize = bufsize; b->maxsize = bufsize; - f1 = b->buf; - f2 = b->tmpbuf; - b->buf = buf; - b->tmpbuf = tmpbuf; - f3 = b->shadbuf; - b->shadbuf = shadbuf; b->sl = bufsize; sndbuf_reset(b); - chn_unlock(b->channel); - if (f1) - free(f1, M_DEVBUF); - if (f2) - free(f2, M_DEVBUF); - if (f3) - free(f3, M_DEVBUF); - - ret = 0; - - chn_lock(b->channel); - return ret; + return 0; } /** @@ -409,6 +422,12 @@ sndbuf_getmaxsize(struct snd_dbuf *b) } unsigned int +sndbuf_getallocsize(struct snd_dbuf *b) +{ + return b->allocsize; +} + +unsigned int sndbuf_runsz(struct snd_dbuf *b) { return b->dl; diff --git a/sys/dev/sound/pcm/buffer.h b/sys/dev/sound/pcm/buffer.h index bd2d801..a21c8ec 100644 --- a/sys/dev/sound/pcm/buffer.h +++ b/sys/dev/sound/pcm/buffer.h @@ -41,7 +41,7 @@ struct snd_dbuf { u_int8_t *buf, *tmpbuf; u_int8_t *shadbuf; /**< shadow buffer used w/ S_D_SILENCE/SKIP */ volatile int sl; /**< shadbuf ready length in # of bytes */ - unsigned int bufsize, maxsize; + unsigned int bufsize, maxsize, allocsize; volatile int dl; /* transfer size */ volatile int rp; /* pointers to the ready area */ volatile int rl; /* length of ready area */ @@ -89,6 +89,7 @@ void *sndbuf_getbuf(struct snd_dbuf *b); void *sndbuf_getbufofs(struct snd_dbuf *b, unsigned int ofs); unsigned int sndbuf_getsize(struct snd_dbuf *b); unsigned int sndbuf_getmaxsize(struct snd_dbuf *b); +unsigned int sndbuf_getallocsize(struct snd_dbuf *b); unsigned int sndbuf_getalign(struct snd_dbuf *b); unsigned int sndbuf_getblkcnt(struct snd_dbuf *b); void sndbuf_setblkcnt(struct snd_dbuf *b, unsigned int blkcnt); -- cgit v1.1