Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pad pad(4): Refactor for clarity, and fix locking bugs.
details: https://anonhg.NetBSD.org/src/rev/0b7a232e3ec7
branches: trunk
changeset: 379688:0b7a232e3ec7
user: riastradh <riastradh%NetBSD.org@localhost>
date: Mon Jun 14 18:44:37 2021 +0000
description:
pad(4): Refactor for clarity, and fix locking bugs.
- Don't touch sc_buflen outside sc_intr_lock.
- Omit needless broadcast in pad_halt_output -- nothing wakes on the
new condition (sc_buflen == 0), so this can't make a difference
except possibly in buggy code.
- Sprinkle KASSERTs.
diffstat:
sys/dev/pad/pad.c | 57 +++++++++++++++++++++++++++---------------------------
1 files changed, 29 insertions(+), 28 deletions(-)
diffs (129 lines):
diff -r 91ed6817f913 -r 0b7a232e3ec7 sys/dev/pad/pad.c
--- a/sys/dev/pad/pad.c Mon Jun 14 17:22:22 2021 +0000
+++ b/sys/dev/pad/pad.c Mon Jun 14 18:44:37 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pad.c,v 1.72 2021/06/14 10:21:21 riastradh Exp $ */
+/* $NetBSD: pad.c,v 1.73 2021/06/14 18:44:37 riastradh 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.72 2021/06/14 10:21:21 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pad.c,v 1.73 2021/06/14 18:44:37 riastradh Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -271,6 +271,8 @@ pad_childdet(device_t self, device_t chi
{
struct pad_softc *sc = device_private(self);
+ KASSERT(KERNEL_LOCKED_P());
+
if (child == sc->sc_audiodev)
sc->sc_audiodev = NULL;
}
@@ -280,7 +282,11 @@ pad_add_block(struct pad_softc *sc, uint
{
int l;
- if (sc->sc_buflen + blksize > PAD_BUFSIZE)
+ KASSERT(blksize >= 0);
+ KASSERT(mutex_owned(&sc->sc_intr_lock));
+
+ if (blksize > PAD_BUFSIZE ||
+ sc->sc_buflen > PAD_BUFSIZE - (unsigned)blksize)
return ENOBUFS;
if (sc->sc_wpos + blksize <= PAD_BUFSIZE)
@@ -296,16 +302,27 @@ pad_add_block(struct pad_softc *sc, uint
sc->sc_wpos -= PAD_BUFSIZE;
sc->sc_buflen += blksize;
+ cv_broadcast(&sc->sc_condvar);
return 0;
}
static int
-pad_get_block(struct pad_softc *sc, pad_block_t *pb, int blksize)
+pad_get_block(struct pad_softc *sc, pad_block_t *pb, int maxblksize)
{
- int l;
+ int l, blksize, error;
+
+ KASSERT(maxblksize > 0);
+ KASSERT(mutex_owned(&sc->sc_intr_lock));
- KASSERT(pb != NULL);
+ while (sc->sc_buflen == 0) {
+ DPRINTF("%s: wait\n", __func__);
+ error = cv_wait_sig(&sc->sc_condvar, &sc->sc_intr_lock);
+ DPRINTF("%s: wake up %d\n", __func__, err);
+ if (error)
+ return error;
+ }
+ blksize = uimin(maxblksize, sc->sc_buflen);
pb->pb_ptr = (sc->sc_audiobuf + sc->sc_rpos);
if (sc->sc_rpos + blksize < PAD_BUFSIZE) {
@@ -453,35 +470,21 @@ pad_read(struct pad_softc *sc, off_t *of
int ioflag)
{
pad_block_t pb;
- int len;
int err;
err = 0;
DPRINTF("%s: resid=%zu\n", __func__, uio->uio_resid);
- while (uio->uio_resid > 0 && !err) {
+ while (uio->uio_resid > 0) {
mutex_enter(&sc->sc_intr_lock);
- if (sc->sc_buflen == 0) {
- DPRINTF("%s: wait\n", __func__);
- err = cv_wait_sig(&sc->sc_condvar, &sc->sc_intr_lock);
- DPRINTF("%s: wake up %d\n", __func__, err);
- mutex_exit(&sc->sc_intr_lock);
- if (err) {
- if (err == ERESTART)
- err = EINTR;
- break;
- }
- if (sc->sc_buflen == 0)
- break;
- continue;
- }
-
- len = uimin(uio->uio_resid, sc->sc_buflen);
- err = pad_get_block(sc, &pb, len);
+ err = pad_get_block(sc, &pb, uio->uio_resid);
mutex_exit(&sc->sc_intr_lock);
if (err)
break;
+
DPRINTF("%s: move %d\n", __func__, pb.pb_len);
- uiomove(pb.pb_ptr, pb.pb_len, uio);
+ err = uiomove(pb.pb_ptr, pb.pb_len, uio);
+ if (err)
+ break;
}
return err;
@@ -534,7 +537,6 @@ pad_start_output(void *opaque, void *blo
DPRINTF("%s: blksize=%d\n", __func__, blksize);
err = pad_add_block(sc, block, blksize);
- cv_broadcast(&sc->sc_condvar);
ms = blksize * 1000 / PADCHAN / (PADPREC / NBBY) / PADFREQ;
DPRINTF("%s: callout ms=%d\n", __func__, ms);
@@ -557,7 +559,6 @@ pad_halt_output(void *opaque)
sc->sc_intrarg = NULL;
sc->sc_buflen = 0;
sc->sc_rpos = sc->sc_wpos = 0;
- cv_broadcast(&sc->sc_condvar);
return 0;
}
Home |
Main Index |
Thread Index |
Old Index