Module Name: src
Committed By: mlelstv
Date: Sun Feb 16 21:09:00 UTC 2025
Modified Files:
src/sys/dev: video.c
Log Message:
When dropping lock around scatter_io_uiomove(), use busy flag
to serialize operations.
Hold lock while accessing video_stream and video_buffer.
To generate a diff of this commit:
cvs rdiff -u -r1.45 -r1.46 src/sys/dev/video.c
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/video.c
diff -u src/sys/dev/video.c:1.45 src/sys/dev/video.c:1.46
--- src/sys/dev/video.c:1.45 Thu Mar 3 06:23:25 2022
+++ src/sys/dev/video.c Sun Feb 16 21:09:00 2025
@@ -1,4 +1,4 @@
-/* $NetBSD: video.c,v 1.45 2022/03/03 06:23:25 riastradh Exp $ */
+/* $NetBSD: video.c,v 1.46 2025/02/16 21:09:00 mlelstv Exp $ */
/*
* Copyright (c) 2008 Patrick Mahoney <[email protected]>
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: video.c,v 1.45 2022/03/03 06:23:25 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: video.c,v 1.46 2025/02/16 21:09:00 mlelstv Exp $");
#include "video.h"
#if NVIDEO > 0
@@ -125,6 +125,7 @@ enum video_stream_method {
struct video_buffer {
struct v4l2_buffer *vb_buf;
SIMPLEQ_ENTRY(video_buffer) entries;
+ u_int busy;
};
SIMPLEQ_HEAD(sample_queue, video_buffer);
@@ -1796,7 +1797,7 @@ videoread(dev_t dev, struct uio *uio, in
struct video_buffer *vb;
struct scatter_io sio;
int err;
- size_t len;
+ size_t len, done;
off_t offset;
sc = device_private(device_lookup(&video_cd, VIDEOUNIT(dev)));
@@ -1855,31 +1856,54 @@ retry:
goto retry;
}
- mutex_exit(&vs->vs_lock);
+ if (vb->busy) {
+ if (vs->vs_flags & O_NONBLOCK) {
+ mutex_exit(&vs->vs_lock);
+ return EAGAIN;
+ }
+
+ while (vb->busy > 0) {
+ err = cv_wait_sig(&vs->vs_sample_cv, &vs->vs_lock);
+ if (err != 0) {
+ mutex_exit(&vs->vs_lock);
+ return EINTR;
+ }
+ }
+ }
+
+ vb->busy++;
len = uimin(uio->uio_resid, vb->vb_buf->bytesused - vs->vs_bytesread);
offset = vb->vb_buf->m.offset + vs->vs_bytesread;
+ mutex_exit(&vs->vs_lock);
+
+ done = 0;
if (scatter_io_init(&vs->vs_data, offset, len, &sio)) {
err = scatter_io_uiomove(&sio, uio);
if (err == EFAULT)
return EFAULT;
- vs->vs_bytesread += (len - sio.sio_resid);
+ done = len - sio.sio_resid;
} else {
DPRINTF(("video: invalid read\n"));
}
/* Move the sample to the ingress queue if everything has
* been read */
+ mutex_enter(&vs->vs_lock);
+
+ if (--vb->busy <= 0)
+ cv_signal(&vs->vs_sample_cv);
+
+ vs->vs_bytesread += done;
if (vs->vs_bytesread >= vb->vb_buf->bytesused) {
- mutex_enter(&vs->vs_lock);
vb = video_stream_dequeue(vs);
video_stream_enqueue(vs, vb);
- mutex_exit(&vs->vs_lock);
-
vs->vs_bytesread = 0;
}
+ mutex_exit(&vs->vs_lock);
+
return 0;
}