git: fe13f70b95a7 - main - sound: Include more information in kevent returned from the kernel

From: Christos Margiolis <christos_at_FreeBSD.org>
Date: Wed, 17 Jun 2026 10:52:50 UTC
The branch main has been updated by christos:

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

commit fe13f70b95a762e19c38d1152eac6312d8578f84
Author:     Goran Mekić <meka@tilda.center>
AuthorDate: 2026-06-17 10:35:07 +0000
Commit:     Christos Margiolis <christos@FreeBSD.org>
CommitDate: 2026-06-17 10:50:39 +0000

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

diff --git a/share/man/man4/pcm.4 b/share/man/man4/pcm.4
index 181b2120c2e6..cda27d734b74 100644
--- a/share/man/man4/pcm.4
+++ b/share/man/man4/pcm.4
@@ -23,7 +23,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd May 21, 2026
+.Dd June 17, 2026
 .Dt SOUND 4
 .Os
 .Sh NAME
@@ -529,6 +529,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 1fa665b6b6cf..7f05da62a173 100644
--- a/sys/dev/sound/pcm/dsp.c
+++ b/sys/dev/sound/pcm/dsp.c
@@ -3020,10 +3020,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);