git: 4a556c2277fd - main - Revert "sound: Create a dsp_close() helper function"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 25 Apr 2025 22:03:56 UTC
The branch main has been updated by christos: URL: https://cgit.FreeBSD.org/src/commit/?id=4a556c2277fd63d83820099d72e953275a03a814 commit 4a556c2277fd63d83820099d72e953275a03a814 Author: Christos Margiolis <christos@FreeBSD.org> AuthorDate: 2025-04-25 22:02:08 +0000 Commit: Christos Margiolis <christos@FreeBSD.org> CommitDate: 2025-04-25 22:02:08 +0000 Revert "sound: Create a dsp_close() helper function" Committed by accident. This reverts commit 532b45fe103c623855bf1004d5de2fd41e2885e4. --- sys/dev/sound/pcm/dsp.c | 129 +++++++++++++++++++++++++++--------------------- 1 file changed, 74 insertions(+), 55 deletions(-) diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c index 0f7cf0d456cf..bc64b50b4510 100644 --- a/sys/dev/sound/pcm/dsp.c +++ b/sys/dev/sound/pcm/dsp.c @@ -97,7 +97,6 @@ struct cdevsw dsp_cdevsw = { static eventhandler_tag dsp_ehtag = NULL; -static void dsp_close_chan(struct pcm_channel *c); static int dsp_oss_syncgroup(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_syncgroup *group); static int dsp_oss_syncstart(int sg_id); static int dsp_oss_policy(struct pcm_channel *wrch, struct pcm_channel *rdch, int policy); @@ -242,19 +241,20 @@ dsp_chn_alloc(struct snddev_info *d, struct pcm_channel **ch, int direction, } static void -dsp_close_chan(struct pcm_channel *c) +dsp_close(void *data) { + struct dsp_cdevpriv *priv = data; + struct pcm_channel *rdch, *wrch, *parent; struct snddev_info *d; - struct pcm_channel *parent; int sg_ids; - if (c == NULL) + if (priv == NULL) return; - d = c->parentsnddev; + d = priv->sc; /* At this point pcm_unregister() will destroy all channels anyway. */ if (!DSP_REGISTERED(d)) - return; + goto skip; PCM_GIANT_ENTER(d); @@ -262,63 +262,82 @@ dsp_close_chan(struct pcm_channel *c) PCM_WAIT(d); PCM_ACQUIRE(d); - CHN_REMOVE(d, c, channels.pcm.opened); - - PCM_UNLOCK(d); + rdch = priv->rdch; + wrch = priv->wrch; - /* - * The channel itself need not be locked because: - * a) Adding a channel to a syncgroup happens only in dsp_ioctl(), - * which cannot run concurrently to dsp_close_chan(). - * b) The syncmember pointer (sm) is protected by the global - * syncgroup list lock. - * c) A channel can't just disappear, invalidating pointers, unless - * it's closed/dereferenced first. - */ - PCM_SG_LOCK(); - sg_ids = chn_syncdestroy(c); - PCM_SG_UNLOCK(); - if (sg_ids != 0) - free_unr(pcmsg_unrhdr, sg_ids); + if (rdch != NULL) + CHN_REMOVE(d, rdch, channels.pcm.opened); + if (wrch != NULL) + CHN_REMOVE(d, wrch, channels.pcm.opened); - if (c->flags & CHN_F_VIRTUAL) { - parent = c->parentchannel; - CHN_LOCK(parent); - CHN_LOCK(c); - vchan_destroy(c); - CHN_UNLOCK(parent); - } else { - CHN_LOCK(c); - if (c->direction == PCMDIR_REC) - chn_abort(c); /* won't sleep */ - else - chn_flush(c); /* may sleep */ - c->flags &= ~(CHN_F_RUNNING | CHN_F_MMAP | CHN_F_DEAD | - CHN_F_EXCLUSIVE); - chn_reset(c, 0, 0); - chn_release(c); + if (rdch != NULL || wrch != NULL) { + PCM_UNLOCK(d); + if (rdch != NULL) { + /* + * The channel itself need not be locked because: + * a) Adding a channel to a syncgroup happens only + * in dsp_ioctl(), which cannot run concurrently + * to dsp_close(). + * b) The syncmember pointer (sm) is protected by + * the global syncgroup list lock. + * c) A channel can't just disappear, invalidating + * pointers, unless it's closed/dereferenced + * first. + */ + PCM_SG_LOCK(); + sg_ids = chn_syncdestroy(rdch); + PCM_SG_UNLOCK(); + if (sg_ids != 0) + free_unr(pcmsg_unrhdr, sg_ids); + + if (rdch->flags & CHN_F_VIRTUAL) { + parent = rdch->parentchannel; + CHN_LOCK(parent); + CHN_LOCK(rdch); + vchan_destroy(rdch); + CHN_UNLOCK(parent); + } else { + CHN_LOCK(rdch); + 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); + chn_release(rdch); + } + } + if (wrch != NULL) { + /* + * Please see block above. + */ + PCM_SG_LOCK(); + sg_ids = chn_syncdestroy(wrch); + PCM_SG_UNLOCK(); + if (sg_ids != 0) + free_unr(pcmsg_unrhdr, sg_ids); + + if (wrch->flags & CHN_F_VIRTUAL) { + parent = wrch->parentchannel; + CHN_LOCK(parent); + CHN_LOCK(wrch); + vchan_destroy(wrch); + CHN_UNLOCK(parent); + } else { + CHN_LOCK(wrch); + chn_flush(wrch); /* may sleep */ + wrch->flags &= ~(CHN_F_RUNNING | CHN_F_MMAP | + CHN_F_DEAD | CHN_F_EXCLUSIVE); + chn_reset(wrch, 0, 0); + chn_release(wrch); + } + } + PCM_LOCK(d); } - PCM_LOCK(d); - PCM_RELEASE(d); PCM_UNLOCK(d); PCM_GIANT_LEAVE(d); -} - - -static void -dsp_close(void *data) -{ - struct dsp_cdevpriv *priv = data; - - if (priv == NULL) - return; - - dsp_close_chan(priv->rdch); - dsp_close_chan(priv->wrch); - +skip: free(priv, M_DEVBUF); priv = NULL; }