sound: Move pcm_chnref() and pcm_chnrelease() to pcm/channel.c

Improve code layering. These are channel functions, and so they do not
belong in pcm/sound.c.

While here, assert in chn_ref() that new refcount won't be negative.

Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Reviewed by:	markj
Differential Revision:	https://reviews.freebsd.org/D44985
This commit is contained in:
Christos Margiolis 2024-04-28 21:46:55 +02:00
parent b3ea087c05
commit a24050e2b7
5 changed files with 43 additions and 41 deletions

View file

@ -1314,6 +1314,34 @@ chn_shutdown(struct pcm_channel *c)
c->flags |= CHN_F_DEAD;
}
/* release a locked channel and unlock it */
int
chn_release(struct pcm_channel *c)
{
PCM_BUSYASSERT(c->parentsnddev);
CHN_LOCKASSERT(c);
c->flags &= ~CHN_F_BUSY;
c->pid = -1;
strlcpy(c->comm, CHN_COMM_UNUSED, sizeof(c->comm));
CHN_UNLOCK(c);
return (0);
}
int
chn_ref(struct pcm_channel *c, int ref)
{
PCM_BUSYASSERT(c->parentsnddev);
CHN_LOCKASSERT(c);
KASSERT((c->refcount + ref) >= 0,
("%s(): new refcount will be negative", __func__));
c->refcount += ref;
return (c->refcount);
}
int
chn_setvolume_multi(struct pcm_channel *c, int vc, int left, int right,
int center)

View file

@ -262,6 +262,8 @@ int chn_poll(struct pcm_channel *c, int ev, struct thread *td);
int chn_init(struct pcm_channel *c, void *devinfo, int dir, int direction);
void chn_kill(struct pcm_channel *c);
void chn_shutdown(struct pcm_channel *c);
int chn_release(struct pcm_channel *c);
int chn_ref(struct pcm_channel *c, int ref);
int chn_reset(struct pcm_channel *c, u_int32_t fmt, u_int32_t spd);
int chn_setvolume_multi(struct pcm_channel *c, int vc, int left, int right,
int center);

View file

@ -181,8 +181,8 @@ getchns(struct dsp_cdevpriv *priv, uint32_t prio)
pcm_setflags(d->dev, flags);
if (ch != NULL) {
CHN_LOCK(ch);
pcm_chnref(ch, -1);
pcm_chnrelease(ch);
chn_ref(ch, -1);
chn_release(ch);
}
PCM_RELEASE(d);
PCM_UNLOCK(d);
@ -301,7 +301,7 @@ dsp_close(void *data)
wdref--;
else {
CHN_LOCK(volch);
pcm_chnref(volch, -1);
chn_ref(volch, -1);
CHN_UNLOCK(volch);
}
}
@ -332,12 +332,12 @@ dsp_close(void *data)
free_unr(pcmsg_unrhdr, sg_ids);
CHN_LOCK(rdch);
pcm_chnref(rdch, rdref);
chn_ref(rdch, rdref);
chn_abort(rdch); /* won't sleep */
rdch->flags &= ~(CHN_F_RUNNING | CHN_F_MMAP |
CHN_F_DEAD | CHN_F_EXCLUSIVE);
chn_reset(rdch, 0, 0);
pcm_chnrelease(rdch);
chn_release(rdch);
}
if (wrch != NULL) {
/*
@ -350,12 +350,12 @@ dsp_close(void *data)
free_unr(pcmsg_unrhdr, sg_ids);
CHN_LOCK(wrch);
pcm_chnref(wrch, wdref);
chn_ref(wrch, wdref);
chn_flush(wrch); /* may sleep */
wrch->flags &= ~(CHN_F_RUNNING | CHN_F_MMAP |
CHN_F_DEAD | CHN_F_EXCLUSIVE);
chn_reset(wrch, 0, 0);
pcm_chnrelease(wrch);
chn_release(wrch);
}
PCM_LOCK(d);
}
@ -451,7 +451,7 @@ dsp_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
if (rderror != 0) {
if (rdch != NULL)
pcm_chnrelease(rdch);
chn_release(rdch);
if (!DSP_F_DUPLEX(flags)) {
PCM_RELEASE_QUICK(d);
PCM_GIANT_EXIT(d);
@ -463,7 +463,7 @@ dsp_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
rdch->flags |= CHN_F_NBIO;
if (flags & O_EXCL)
rdch->flags |= CHN_F_EXCLUSIVE;
pcm_chnref(rdch, 1);
chn_ref(rdch, 1);
chn_vpc_reset(rdch, SND_VOL_C_PCM, 0);
CHN_UNLOCK(rdch);
}
@ -479,7 +479,7 @@ dsp_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
if (wrerror != 0) {
if (wrch != NULL)
pcm_chnrelease(wrch);
chn_release(wrch);
if (!DSP_F_DUPLEX(flags)) {
if (rdch != NULL) {
/*
@ -487,8 +487,8 @@ dsp_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
* created record channel
*/
CHN_LOCK(rdch);
pcm_chnref(rdch, -1);
pcm_chnrelease(rdch);
chn_ref(rdch, -1);
chn_release(rdch);
}
PCM_RELEASE_QUICK(d);
PCM_GIANT_EXIT(d);
@ -500,7 +500,7 @@ dsp_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
wrch->flags |= CHN_F_NBIO;
if (flags & O_EXCL)
wrch->flags |= CHN_F_EXCLUSIVE;
pcm_chnref(wrch, 1);
chn_ref(wrch, 1);
chn_vpc_reset(wrch, SND_VOL_C_PCM, 0);
CHN_UNLOCK(wrch);
}

View file

@ -306,32 +306,6 @@ pcm_chnalloc(struct snddev_info *d, struct pcm_channel **ch, int direction,
return (err);
}
/* release a locked channel and unlock it */
int
pcm_chnrelease(struct pcm_channel *c)
{
PCM_BUSYASSERT(c->parentsnddev);
CHN_LOCKASSERT(c);
c->flags &= ~CHN_F_BUSY;
c->pid = -1;
strlcpy(c->comm, CHN_COMM_UNUSED, sizeof(c->comm));
CHN_UNLOCK(c);
return (0);
}
int
pcm_chnref(struct pcm_channel *c, int ref)
{
PCM_BUSYASSERT(c->parentsnddev);
CHN_LOCKASSERT(c);
c->refcount += ref;
return (c->refcount);
}
static void
pcm_setmaxautovchans(struct snddev_info *d, int num)
{

View file

@ -296,8 +296,6 @@ SYSCTL_DECL(_hw_snd);
int pcm_setvchans(struct snddev_info *d, int direction, int newcnt, int num);
int pcm_chnalloc(struct snddev_info *d, struct pcm_channel **ch, int direction,
pid_t pid, char *comm);
int pcm_chnrelease(struct pcm_channel *c);
int pcm_chnref(struct pcm_channel *c, int ref);
struct pcm_channel *pcm_chn_create(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls, int dir, int num, void *devinfo);
int pcm_chn_add(struct snddev_info *d, struct pcm_channel *ch);