diff --git a/sys/dev/sound/pcm/channel.h b/sys/dev/sound/pcm/channel.h --- a/sys/dev/sound/pcm/channel.h +++ b/sys/dev/sound/pcm/channel.h @@ -117,6 +117,8 @@ * 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 @@ (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 @@ #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/channel.c b/sys/dev/sound/pcm/channel.c --- a/sys/dev/sound/pcm/channel.c +++ b/sys/dev/sound/pcm/channel.c @@ -329,7 +329,9 @@ 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/sound.h b/sys/dev/sound/pcm/sound.h --- a/sys/dev/sound/pcm/sound.h +++ b/sys/dev/sound/pcm/sound.h @@ -359,15 +359,7 @@ __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 @@ ("%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. */ diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c --- a/sys/dev/sound/pcm/sound.c +++ b/sys/dev/sound/pcm/sound.c @@ -221,8 +221,8 @@ /* 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; }