Module Name: src Committed By: nat Date: Fri Feb 26 13:17:04 UTC 2016
Modified Files: src/sys/dev/pad: pad.c padvar.h Log Message: Allow reads from pad(4) less or greater than PAD_BLKSIZE. Ensure that audio data is ready before reading. Addresses PR 39204. OK jmcneil@. To generate a diff of this commit: cvs rdiff -u -r1.23 -r1.24 src/sys/dev/pad/pad.c cvs rdiff -u -r1.5 -r1.6 src/sys/dev/pad/padvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pad/pad.c diff -u src/sys/dev/pad/pad.c:1.23 src/sys/dev/pad/pad.c:1.24 --- src/sys/dev/pad/pad.c:1.23 Fri Jul 10 21:58:56 2015 +++ src/sys/dev/pad/pad.c Fri Feb 26 13:17:04 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: pad.c,v 1.23 2015/07/10 21:58:56 nat Exp $ */ +/* $NetBSD: pad.c,v 1.24 2016/02/26 13:17:04 nat Exp $ */ /*- * Copyright (c) 2007 Jared D. McNeill <jmcne...@invisible.ca> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pad.c,v 1.23 2015/07/10 21:58:56 nat Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pad.c,v 1.24 2016/02/26 13:17:04 nat Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -43,6 +43,7 @@ __KERNEL_RCSID(0, "$NetBSD: pad.c,v 1.23 #include <sys/vnode.h> #include <sys/module.h> #include <sys/atomic.h> +#include <sys/time.h> #include <dev/audio_if.h> #include <dev/audiovar.h> @@ -316,6 +317,9 @@ pad_open(dev_t dev, int flags, int fmt, if (atomic_swap_uint(&sc->sc_open, 1) != 0) { return EBUSY; } + + getmicrotime(&sc->sc_last); + sc->sc_bytes_count = 0; return 0; } @@ -335,14 +339,20 @@ pad_close(dev_t dev, int flags, int fmt, return 0; } +#define PAD_BYTES_PER_SEC (44100 * sizeof(int16_t) * 2) +#define TIMENEXTREAD (20 * 1000) +#define BYTESTOSLEEP (PAD_BYTES_PER_SEC / (1000000 / TIMENEXTREAD)) + int pad_read(dev_t dev, struct uio *uio, int flags) { + struct timeval now; + uint64_t nowusec, lastusec; pad_softc_t *sc; pad_block_t pb; void (*intr)(void *); void *intrarg; - int err; + int err, wait_ticks; sc = device_lookup_private(&pad_cd, PADUNIT(dev)); if (sc == NULL) @@ -354,10 +364,32 @@ pad_read(dev_t dev, struct uio *uio, int intr = sc->sc_intr; intrarg = sc->sc_intrarg; - kpreempt_disable(); while (uio->uio_resid > 0 && !err) { + getmicrotime(&now); + nowusec = (now.tv_sec * 1000000) + now.tv_usec; + lastusec = (sc->sc_last.tv_sec * 1000000) + + sc->sc_last.tv_usec; + if (lastusec + TIMENEXTREAD > nowusec && + sc->sc_bytes_count >= BYTESTOSLEEP) { + wait_ticks = (hz * ((lastusec + TIMENEXTREAD) - + nowusec)) / 1000000; + if (wait_ticks > 0) { + kpause("padwait", TRUE, wait_ticks, + &sc->sc_lock); + } + + sc->sc_bytes_count -= BYTESTOSLEEP; + getmicrotime(&sc->sc_last); + } else if (sc->sc_bytes_count >= BYTESTOSLEEP) { + sc->sc_bytes_count -= BYTESTOSLEEP; + getmicrotime(&sc->sc_last); + } else if (lastusec + TIMENEXTREAD <= nowusec) + getmicrotime(&sc->sc_last); + err = pad_get_block(sc, &pb, min(uio->uio_resid, PAD_BLKSIZE)); if (!err) { + sc->sc_bytes_count += pb.pb_len; + mutex_exit(&sc->sc_lock); err = uiomove(pb.pb_ptr, pb.pb_len, uio); mutex_enter(&sc->sc_lock); @@ -366,7 +398,9 @@ pad_read(dev_t dev, struct uio *uio, int if (intr) { mutex_enter(&sc->sc_intr_lock); + kpreempt_disable(); (*intr)(intrarg); + kpreempt_enable(); mutex_exit(&sc->sc_intr_lock); intr = sc->sc_intr; intrarg = sc->sc_intrarg; @@ -374,22 +408,13 @@ pad_read(dev_t dev, struct uio *uio, int continue; } err = cv_wait_sig(&sc->sc_condvar, &sc->sc_lock); - if (err != 0) { - mutex_exit(&sc->sc_lock); - kpreempt_enable(); - return err; - } + if (err != 0) + break; + intr = sc->sc_intr; intrarg = sc->sc_intrarg; } - - if (intr) { - mutex_enter(&sc->sc_intr_lock); - (*intr)(intrarg); - mutex_exit(&sc->sc_intr_lock); - } mutex_exit(&sc->sc_lock); - kpreempt_enable(); return err; } Index: src/sys/dev/pad/padvar.h diff -u src/sys/dev/pad/padvar.h:1.5 src/sys/dev/pad/padvar.h:1.6 --- src/sys/dev/pad/padvar.h:1.5 Tue Nov 18 01:53:17 2014 +++ src/sys/dev/pad/padvar.h Fri Feb 26 13:17:04 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: padvar.h,v 1.5 2014/11/18 01:53:17 jmcneill Exp $ */ +/* $NetBSD: padvar.h,v 1.6 2016/02/26 13:17:04 nat Exp $ */ /*- * Copyright (c) 2007 Jared D. McNeill <jmcne...@invisible.ca> @@ -51,6 +51,8 @@ typedef struct pad_softc { uint32_t sc_rpos, sc_wpos; uint8_t sc_swvol; + struct timeval sc_last; + int sc_bytes_count; } pad_softc_t; #endif /* !_SYS_DEV_PAD_PADVAR_H */