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 <p...@polycrystal.org>
@@ -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;
 }
 

Reply via email to