Page MenuHomeFreeBSD

D53029.id165330.diff
No OneTemporary

D53029.id165330.diff

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
@@ -261,6 +261,7 @@
u_int32_t chn_start(struct pcm_channel *c, int force);
int chn_sync(struct pcm_channel *c, int threshold);
int chn_flush(struct pcm_channel *c);
+int chn_polltrigger(struct pcm_channel *c);
int chn_poll(struct pcm_channel *c, int ev, struct thread *td);
char *chn_mkname(char *buf, size_t len, struct pcm_channel *c);
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
@@ -271,7 +271,7 @@
* @retval 1 = ready for I/O
* @retval 0 = not ready for I/O
*/
-static int
+int
chn_polltrigger(struct pcm_channel *c)
{
struct snd_dbuf *bs = c->bufsoft;
@@ -313,6 +313,7 @@
bs = c->bufsoft;
if (CHN_EMPTY(c, children.busy)) {
+ KNOTE_LOCKED(&bs->sel.si_note, 0);
if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c))
selwakeuppri(sndbuf_getsel(bs), PRIBIO);
CHN_BROADCAST(&c->intr_cv);
@@ -1277,6 +1278,7 @@
}
c->bufhard = b;
c->bufsoft = bs;
+ knlist_init_mtx(&bs->sel.si_note, c->lock);
c->devinfo = CHANNEL_INIT(c->methods, devinfo, b, c, direction);
if (c->devinfo == NULL) {
@@ -1373,8 +1375,11 @@
feeder_remove(c);
if (c->devinfo && CHANNEL_FREE(c->methods, c->devinfo))
sndbuf_free(b);
- if (bs)
+ if (bs) {
+ knlist_clear(&bs->sel.si_note, 0);
+ knlist_destroy(&bs->sel.si_note);
sndbuf_destroy(bs);
+ }
if (b)
sndbuf_destroy(b);
CHN_LOCK(c);
diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c
--- a/sys/dev/sound/pcm/dsp.c
+++ b/sys/dev/sound/pcm/dsp.c
@@ -81,6 +81,7 @@
static d_poll_t dsp_poll;
static d_mmap_t dsp_mmap;
static d_mmap_single_t dsp_mmap_single;
+static d_kqfilter_t dsp_kqfilter;
struct cdevsw dsp_cdevsw = {
.d_version = D_VERSION,
@@ -89,6 +90,7 @@
.d_write = dsp_write,
.d_ioctl = dsp_ioctl,
.d_poll = dsp_poll,
+ .d_kqfilter = dsp_kqfilter,
.d_mmap = dsp_mmap,
.d_mmap_single = dsp_mmap_single,
.d_name = "dsp",
@@ -2962,6 +2964,127 @@
return (ret);
}
+static void
+dsp_kqdetach(struct knote *kn)
+{
+ struct dsp_cdevpriv *priv = kn->kn_hook;
+ struct snddev_info *d;
+ struct pcm_channel *ch;
+
+ d = priv->sc;
+ if (!DSP_REGISTERED(d))
+ return;
+ switch (kn->kn_filter) {
+ case EVFILT_READ:
+ ch = priv->rdch;
+ break;
+ case EVFILT_WRITE:
+ ch = priv->wrch;
+ break;
+ default:
+ return;
+ }
+ if (ch != NULL) {
+ CHN_LOCK(ch);
+ knlist_remove(&ch->bufsoft->sel.si_note, kn, 1);
+ CHN_UNLOCK(ch);
+ }
+}
+
+static int
+dsp_kqevent(struct knote *kn, long hint)
+{
+ struct dsp_cdevpriv *priv = kn->kn_hook;
+ struct snddev_info *d;
+ struct pcm_channel *ch;
+
+ d = priv->sc;
+ if (!DSP_REGISTERED(d)) {
+ kn->kn_data = EBADF;
+ goto error;
+ }
+ switch (kn->kn_filter) {
+ case EVFILT_READ:
+ ch = priv->rdch;
+ break;
+ case EVFILT_WRITE:
+ ch = priv->wrch;
+ break;
+ default:
+ kn->kn_data = EINVAL;
+ goto error;
+ }
+ if (ch != NULL) {
+ CHN_LOCKASSERT(ch);
+ if (ch->flags & CHN_F_DEAD) {
+ kn->kn_data = ENODEV;
+ goto error;
+ }
+ kn->kn_data = 0;
+ if (chn_polltrigger(ch)) {
+ if (kn->kn_filter == EVFILT_READ)
+ kn->kn_data = sndbuf_getready(ch->bufsoft);
+ else
+ kn->kn_data = sndbuf_getfree(ch->bufsoft);
+ }
+ }
+
+ return (kn->kn_data > 0);
+error:
+ kn->kn_flags |= EV_ERROR;
+
+ return (1);
+}
+
+static const struct filterops dsp_filtops = {
+ .f_isfd = 1,
+ .f_detach = dsp_kqdetach,
+ .f_event = dsp_kqevent,
+};
+
+static int
+dsp_kqfilter(struct cdev *dev, struct knote *kn)
+{
+ struct dsp_cdevpriv *priv;
+ struct snddev_info *d;
+ struct pcm_channel *ch;
+ int err = 0;
+
+ if ((err = devfs_get_cdevpriv((void **)&priv)) != 0)
+ return (err);
+
+ d = priv->sc;
+ if (!DSP_REGISTERED(d))
+ return (EBADF);
+ PCM_GIANT_ENTER(d);
+ switch (kn->kn_filter) {
+ case EVFILT_READ:
+ ch = priv->rdch;
+ break;
+ case EVFILT_WRITE:
+ ch = priv->wrch;
+ break;
+ default:
+ kn->kn_hook = NULL;
+ err = EINVAL;
+ ch = NULL;
+ break;
+ }
+ if (ch != NULL) {
+ kn->kn_fop = &dsp_filtops;
+ CHN_LOCK(ch);
+ knlist_add(&ch->bufsoft->sel.si_note, kn, 1);
+ CHN_UNLOCK(ch);
+ } else
+ err = EINVAL;
+ PCM_GIANT_LEAVE(d);
+ if (err == 0)
+ kn->kn_hook = priv;
+
+ return (err);
+}
+
+
#ifdef OSSV4_EXPERIMENT
/**
* @brief Retrieve an audio device's label

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 26, 3:45 PM (45 m, 59 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26218182
Default Alt Text
D53029.id165330.diff (4 KB)

Event Timeline