git: 532b45fe103c - main - sound: Create a dsp_close() helper function
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 25 Apr 2025 16:56:43 UTC
The branch main has been updated by christos:
URL: https://cgit.FreeBSD.org/src/commit/?id=532b45fe103c623855bf1004d5de2fd41e2885e4
commit 532b45fe103c623855bf1004d5de2fd41e2885e4
Author: Christos Margiolis <christos@FreeBSD.org>
AuthorDate: 2025-04-25 16:56:03 +0000
Commit: Christos Margiolis <christos@FreeBSD.org>
CommitDate: 2025-04-25 16:56:22 +0000
sound: Create a dsp_close() helper function
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Reviewed by: kib, markj
Differential Revision: https://reviews.freebsd.org/D49805
---
sys/dev/sound/pcm/dsp.c | 129 +++++++++++++++++++++---------------------------
1 file changed, 55 insertions(+), 74 deletions(-)
diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c
index bc64b50b4510..0f7cf0d456cf 100644
--- a/sys/dev/sound/pcm/dsp.c
+++ b/sys/dev/sound/pcm/dsp.c
@@ -97,6 +97,7 @@ 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);
@@ -241,20 +242,19 @@ dsp_chn_alloc(struct snddev_info *d, struct pcm_channel **ch, int direction,
}
static void
-dsp_close(void *data)
+dsp_close_chan(struct pcm_channel *c)
{
- struct dsp_cdevpriv *priv = data;
- struct pcm_channel *rdch, *wrch, *parent;
struct snddev_info *d;
+ struct pcm_channel *parent;
int sg_ids;
- if (priv == NULL)
+ if (c == NULL)
return;
- d = priv->sc;
+ d = c->parentsnddev;
/* At this point pcm_unregister() will destroy all channels anyway. */
if (!DSP_REGISTERED(d))
- goto skip;
+ return;
PCM_GIANT_ENTER(d);
@@ -262,82 +262,63 @@ dsp_close(void *data)
PCM_WAIT(d);
PCM_ACQUIRE(d);
- rdch = priv->rdch;
- wrch = priv->wrch;
+ CHN_REMOVE(d, c, channels.pcm.opened);
- if (rdch != NULL)
- CHN_REMOVE(d, rdch, channels.pcm.opened);
- if (wrch != NULL)
- CHN_REMOVE(d, wrch, channels.pcm.opened);
+ PCM_UNLOCK(d);
- 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);
+ /*
+ * 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 (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);
}
+ PCM_LOCK(d);
+
PCM_RELEASE(d);
PCM_UNLOCK(d);
PCM_GIANT_LEAVE(d);
-skip:
+}
+
+
+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);
+
free(priv, M_DEVBUF);
priv = NULL;
}