Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pad Allow reads from pad(4) less or greater than PAD...



details:   https://anonhg.NetBSD.org/src/rev/0784ce5bea3d
branches:  trunk
changeset: 813912:0784ce5bea3d
user:      nat <nat%NetBSD.org@localhost>
date:      Fri Feb 26 13:17:04 2016 +0000

description:
Allow reads from pad(4) less or greater than PAD_BLKSIZE.

Ensure that audio data is ready before reading.
Addresses PR 39204.

OK jmcneil@.

diffstat:

 sys/dev/pad/pad.c    |  57 +++++++++++++++++++++++++++++++++++++--------------
 sys/dev/pad/padvar.h |   4 ++-
 2 files changed, 44 insertions(+), 17 deletions(-)

diffs (146 lines):

diff -r 00e48834a9fa -r 0784ce5bea3d sys/dev/pad/pad.c
--- a/sys/dev/pad/pad.c Fri Feb 26 13:08:28 2016 +0000
+++ b/sys/dev/pad/pad.c Fri Feb 26 13:17:04 2016 +0000
@@ -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 <jmcneill%invisible.ca@localhost>
@@ -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 @@
 #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 @@
        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 @@
        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 @@
        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 @@
 
                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 @@
                        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;
 }
diff -r 00e48834a9fa -r 0784ce5bea3d sys/dev/pad/padvar.h
--- a/sys/dev/pad/padvar.h      Fri Feb 26 13:08:28 2016 +0000
+++ b/sys/dev/pad/padvar.h      Fri Feb 26 13:17:04 2016 +0000
@@ -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 <jmcneill%invisible.ca@localhost>
@@ -51,6 +51,8 @@
        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 */



Home | Main Index | Thread Index | Old Index