Page MenuHomeFreeBSD

D57833.id181109.diff
No OneTemporary

D57833.id181109.diff

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
@@ -3003,6 +3003,7 @@
dsp_kqevent(struct knote *kn, long hint)
{
struct pcm_channel *ch = kn->kn_hook;
+ int fire;
CHN_LOCKASSERT(ch);
if (ch->flags & CHN_F_DEAD) {
@@ -3010,7 +3011,17 @@
return (1);
}
kn->kn_data = 0;
- if (chn_polltrigger(ch)) {
+ /*
+ * The channel's prev_total is global, so one knote resetting it
+ * would interfere with every other knote on the same channel.
+ * Unlike poll/select, kqueue registrations live in the kernel and
+ * must track the low watermark per-knote so use kn_sdata for that.
+ */
+ if (ch->flags & CHN_F_MMAP)
+ fire = (ch->bufsoft->total - (u_int64_t)kn->kn_sdata) >= ch->lw;
+ else
+ fire = chn_polltrigger(ch);
+ if (fire) {
if (kn->kn_filter == EVFILT_READ) {
kn->kn_data = sndbuf_getready(ch->bufsoft);
if (ch->flags & CHN_F_MMAP)
@@ -3025,6 +3036,7 @@
kn->kn_kevent.ext[0] = sndbuf_getready(ch->bufsoft) / ch->bufsoft->align;
}
kn->kn_kevent.ext[1] = ch->xruns;
+ kn->kn_sdata = ch->bufsoft->total;
}
return (kn->kn_data > 0);
@@ -3070,6 +3082,11 @@
knlist_add(&ch->bufsoft->sel.si_note, kn, 1);
CHN_UNLOCK(ch);
kn->kn_hook = ch;
+ /*
+ * Start tracking from the current position so the first event
+ * fires after c->lw additional bytes have been transferred.
+ */
+ kn->kn_sdata = ch->bufsoft->prev_total;
} else
err = EINVAL;
PCM_GIANT_LEAVE(d);

File Metadata

Mime Type
text/plain
Expires
Mon, Sep 7, 3:45 PM (11 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34576691
Default Alt Text
D57833.id181109.diff (1 KB)

Event Timeline