git: 134a275eea7a - stable/14 - sound: Do not access cv_waiters
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 04 Dec 2024 12:04:17 UTC
The branch stable/14 has been updated by christos:
URL: https://cgit.FreeBSD.org/src/commit/?id=134a275eea7a2edf34b4b98cf6f382d7a3618597
commit 134a275eea7a2edf34b4b98cf6f382d7a3618597
Author: Christos Margiolis <christos@FreeBSD.org>
AuthorDate: 2024-12-02 16:26:58 +0000
Commit: Christos Margiolis <christos@FreeBSD.org>
CommitDate: 2024-12-04 12:03:36 +0000
sound: Do not access cv_waiters
Remove uses of cv_waiters in PCM_RELEASE and CHN_BROADCAST, and also use
a counter around cv_timedwait_sig() in chn_sleep(), which is checked in
pcm_killchans(), as opposed to reading cv_waiters directly, which is a
layering violation.
While here, move CHN_BROADCAST below the channel lock operations.
Reported by: avg, jhb, markj
Sponsored by: The FreeBSD Foundation
MFC after: 2 days
Reviewed by: dev_submerge.ch, avg
Differential Revision: https://reviews.freebsd.org/D47780
(cherry picked from commit 46a97b9cd6fd4415270afe4070082ae69ee21035)
---
sys/dev/sound/pcm/channel.c | 2 ++
sys/dev/sound/pcm/channel.h | 9 ++++-----
sys/dev/sound/pcm/sound.c | 4 ++--
sys/dev/sound/pcm/sound.h | 13 ++-----------
4 files changed, 10 insertions(+), 18 deletions(-)
diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c
index 728284b055e5..925a82bb170f 100644
--- a/sys/dev/sound/pcm/channel.c
+++ b/sys/dev/sound/pcm/channel.c
@@ -329,7 +329,9 @@ chn_sleep(struct pcm_channel *c, int timeout)
if (c->flags & CHN_F_DEAD)
return (EINVAL);
+ c->sleeping++;
ret = cv_timedwait_sig(&c->intr_cv, c->lock, timeout);
+ c->sleeping--;
return ((c->flags & CHN_F_DEAD) ? EINVAL : ret);
}
diff --git a/sys/dev/sound/pcm/channel.h b/sys/dev/sound/pcm/channel.h
index 47089aca0745..67f5019f4727 100644
--- a/sys/dev/sound/pcm/channel.h
+++ b/sys/dev/sound/pcm/channel.h
@@ -117,6 +117,8 @@ struct pcm_channel {
* lock.
*/
unsigned int inprog;
+ /* Incrememnt/decrement around cv_timedwait_sig() in chn_sleep(). */
+ unsigned int sleeping;
/**
* Special channel operations should examine @c inprog after acquiring
* lock. If zero, operations may continue. Else, thread should
@@ -242,11 +244,6 @@ struct pcm_channel {
(x)->parentchannel->bufhard != NULL) ? \
(x)->parentchannel->bufhard : (y))
-#define CHN_BROADCAST(x) do { \
- if ((x)->cv_waiters != 0) \
- cv_broadcastpri(x, PRIBIO); \
-} while (0)
-
#include "channel_if.h"
int chn_reinit(struct pcm_channel *c);
@@ -320,6 +317,8 @@ int chn_getpeaks(struct pcm_channel *c, int *lpeak, int *rpeak);
#define CHN_LOCKASSERT(c) mtx_assert((c)->lock, MA_OWNED)
#define CHN_UNLOCKASSERT(c) mtx_assert((c)->lock, MA_NOTOWNED)
+#define CHN_BROADCAST(x) cv_broadcastpri(x, PRIBIO)
+
int snd_fmtvalid(uint32_t fmt, uint32_t *fmtlist);
uint32_t snd_str2afmt(const char *);
diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c
index 761c505fd402..b8f4efea8789 100644
--- a/sys/dev/sound/pcm/sound.c
+++ b/sys/dev/sound/pcm/sound.c
@@ -221,8 +221,8 @@ pcm_killchans(struct snddev_info *d)
/* Make sure all channels are stopped. */
CHN_FOREACH(ch, d, channels.pcm) {
CHN_LOCK(ch);
- if (ch->intr_cv.cv_waiters == 0 && CHN_STOPPED(ch) &&
- ch->inprog == 0) {
+ if (ch->inprog == 0 && ch->sleeping == 0 &&
+ CHN_STOPPED(ch)) {
CHN_UNLOCK(ch);
continue;
}
diff --git a/sys/dev/sound/pcm/sound.h b/sys/dev/sound/pcm/sound.h
index 65e8c3002026..59d9930712b3 100644
--- a/sys/dev/sound/pcm/sound.h
+++ b/sys/dev/sound/pcm/sound.h
@@ -359,15 +359,7 @@ int sound_oss_card_info(oss_card_info *);
__func__, __LINE__); \
if ((x)->flags & SD_F_BUSY) { \
(x)->flags &= ~SD_F_BUSY; \
- if ((x)->cv.cv_waiters != 0) { \
- if ((x)->cv.cv_waiters > 1 && snd_verbose > 3) \
- device_printf((x)->dev, \
- "%s(%d): [PCM RELEASE] " \
- "cv_waiters=%d > 1!\n", \
- __func__, __LINE__, \
- (x)->cv.cv_waiters); \
- cv_broadcast(&(x)->cv); \
- } \
+ cv_broadcast(&(x)->cv); \
} else \
panic("%s(%d): [PCM RELEASE] Releasing non-BUSY cv!", \
__func__, __LINE__); \
@@ -459,8 +451,7 @@ int sound_oss_card_info(oss_card_info *);
("%s(%d): [PCM RELEASE] Releasing non-BUSY cv!", \
__func__, __LINE__)); \
(x)->flags &= ~SD_F_BUSY; \
- if ((x)->cv.cv_waiters != 0) \
- cv_broadcast(&(x)->cv); \
+ cv_broadcast(&(x)->cv); \
} while (0)
/* Quick version, for shorter path. */