summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorariff <ariff@FreeBSD.org>2007-06-14 11:15:51 +0000
committerariff <ariff@FreeBSD.org>2007-06-14 11:15:51 +0000
commitb43d30ed2c855e05b02ead131136784ad708491e (patch)
tree2896e495c969fde151953b94b88f0fc79e4e0c60
parent3567d731719f9ab23a0e67093d33937a5917ba30 (diff)
downloadFreeBSD-src-b43d30ed2c855e05b02ead131136784ad708491e.zip
FreeBSD-src-b43d30ed2c855e05b02ead131136784ad708491e.tar.gz
Buffer optimization and locking cleanup. Don't resize/malloc
unless it is really necessary to ease down unlock/lock sequence.
-rw-r--r--sys/dev/sound/pcm/buffer.c101
-rw-r--r--sys/dev/sound/pcm/buffer.h3
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);
OpenPOWER on IntegriCloud