git: 5347284ba90f - stable/15 - sound: Include more information in kevent returned from the kernel

From: Christos Margiolis <christos_at_FreeBSD.org>
Date: Tue, 30 Jun 2026 06:24:33 UTC
The branch stable/15 has been updated by christos:

URL: https://cgit.FreeBSD.org/src/commit/?id=5347284ba90fd52eeb5d23e50673f23a3b77c8ad

commit 5347284ba90fd52eeb5d23e50673f23a3b77c8ad
Author:     Goran Mekić <meka@tilda.center>
AuthorDate: 2026-06-17 10:35:07 +0000
Commit:     Christos Margiolis <christos@FreeBSD.org>
CommitDate: 2026-06-30 06:23:56 +0000

    sound: Include more information in kevent returned from the kernel
    
    Reviewed by:    christos
    Differential Revision:  https://reviews.freebsd.org/D57362
    
    (cherry picked from commit fe13f70b95a762e19c38d1152eac6312d8578f84)
---
 share/man/man4/pcm.4    | 76 +++++++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/sound/pcm/dsp.c | 14 +++++++--
 2 files changed, 88 insertions(+), 2 deletions(-)

diff --git a/share/man/man4/pcm.4 b/share/man/man4/pcm.4
index 7a0059f43f73..1aebff562d8f 100644
--- a/share/man/man4/pcm.4
+++ b/share/man/man4/pcm.4
@@ -509,6 +509,82 @@ See
 for a complete list of the supported
 .Fn ioctl
 functions.
+.Ss kqueue Support
+The
+.Va kevent
+structure's fields are defined as follows:
+.Bl -tag -width "Fa filter"
+.It Fa ident
+The file descriptor for the device.
+.It Fa filter
+The kernel filter used to process the event.
+This is either
+.Dv EVFILT_READ
+for recording or
+.Dv EVFILT_WRITE
+for playback.
+.It Fa data
+The number of bytes available to be read or written.
+.It Fa ext
+.Bl -bullet -compact
+.It
+.Va ext[0]
+For devices that use
+.Xr mmap 2 ,
+it contains the
+.Va count_info.ptr
+field reported by
+.Va SNDCTL_DSP_GETIPTR
+for recording or
+.Va SNDCTL_DSP_GETOPTR
+for playback, whereas for devices that do not use
+.Xr mmap 2 ,
+it contains the
+.Va oss_count_t.fifo_samples
+field reported by
+.Va SNDCTL_DSP_CURRENT_IPTR
+for recording or
+.Va SNDCTL_DSP_CURRENT_OPTR
+for playback.
+.It
+.Va ext[1]
+contains the
+.Va audio_errinfo.rec_overruns
+field for recording events, or the
+.Va audio_errinfo.play_underruns
+field for playback events, as reported by
+.Va SNDCTL_DSP_GETERROR .
+.Pp
+This allows a single
+.Va kevent
+to report that data is ready, how many bytes can be read or written, the
+current buffer position, and the current error count.
+This is especially useful for scenarios that use
+.Xr mmap 2 ,
+because without
+.Xr kqueue 2
+the typical processing loop consists of:
+.Bl -bullet -compact
+.It
+Calculating the wait time and calling
+.Xr clock_nanosleep 2 .
+.It
+Calling
+.Xr ioctl 2
+for
+.Va SNDCTL_DSP_GETIPTR
+or
+.Va SNDCTL_DSP_GETOPTR
+to get the pointer into the memory-mapped buffer where new data starts.
+.It
+Calling
+.Xr ioctl 2
+for
+.Va SNDCTL_DSP_GETERROR
+to get over/underruns and handle them.
+.El
+.El
+.El
 .Sh FILES
 The
 .Nm
diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c
index f32446570374..fbe9f8a04325 100644
--- a/sys/dev/sound/pcm/dsp.c
+++ b/sys/dev/sound/pcm/dsp.c
@@ -3011,10 +3011,20 @@ dsp_kqevent(struct knote *kn, long hint)
 	}
 	kn->kn_data = 0;
 	if (chn_polltrigger(ch)) {
-		if (kn->kn_filter == EVFILT_READ)
+		if (kn->kn_filter == EVFILT_READ) {
 			kn->kn_data = sndbuf_getready(ch->bufsoft);
-		else
+			if (ch->flags & CHN_F_MMAP)
+				kn->kn_kevent.ext[0] = sndbuf_getfreeptr(ch->bufsoft);
+			else
+				kn->kn_kevent.ext[0] = sndbuf_getready(ch->bufsoft) / ch->bufsoft->align;
+		} else {
 			kn->kn_data = sndbuf_getfree(ch->bufsoft);
+			if (ch->flags & CHN_F_MMAP)
+				kn->kn_kevent.ext[0] = sndbuf_getreadyptr(ch->bufsoft);
+			else
+				kn->kn_kevent.ext[0] = sndbuf_getready(ch->bufsoft) / ch->bufsoft->align;
+		}
+		kn->kn_kevent.ext[1] = ch->xruns;
 	}
 
 	return (kn->kn_data > 0);