[libcamera-devel] [PATCH v3 22/22] v4l2: v4l2_camera_proxy: Serialize accesses to the proxy

Paul Elder paul.elder at ideasonboard.com
Tue Jun 23 21:08:36 CEST 2020


Make the V4L2 compatibility layer thread-safe by serializing accesses to
the V4L2CameraProxy with a lock. Release the lock when blocking for
dqbuf.

Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>

---
New in v3
---
 src/v4l2/v4l2_camera_proxy.cpp | 21 +++++++++++++++++----
 src/v4l2/v4l2_camera_proxy.h   |  5 ++++-
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp
index ed3bcbc..fb3a1fc 100644
--- a/src/v4l2/v4l2_camera_proxy.cpp
+++ b/src/v4l2/v4l2_camera_proxy.cpp
@@ -43,6 +43,8 @@ V4L2CameraProxy::V4L2CameraProxy(unsigned int index,
 
 int V4L2CameraProxy::open(V4L2CameraFile *file)
 {
+	MutexLocker locker(proxyMutex_);
+
 	LOG(V4L2Compat, Debug) << "Servicing open fd = " << file->efd();
 
 	files_.insert(file);
@@ -75,6 +77,8 @@ int V4L2CameraProxy::open(V4L2CameraFile *file)
 
 void V4L2CameraProxy::close(V4L2CameraFile *file)
 {
+	MutexLocker locker(proxyMutex_);
+
 	LOG(V4L2Compat, Debug) << "Servicing close fd = " << file->efd();
 
 	files_.erase(file);
@@ -90,6 +94,8 @@ void V4L2CameraProxy::close(V4L2CameraFile *file)
 void *V4L2CameraProxy::mmap(void *addr, size_t length, int prot, int flags,
 			    off64_t offset)
 {
+	MutexLocker locker(proxyMutex_);
+
 	LOG(V4L2Compat, Debug) << "Servicing mmap";
 
 	/* \todo Validate prot and flags properly. */
@@ -124,6 +130,8 @@ void *V4L2CameraProxy::mmap(void *addr, size_t length, int prot, int flags,
 
 int V4L2CameraProxy::munmap(void *addr, size_t length)
 {
+	MutexLocker locker(proxyMutex_);
+
 	LOG(V4L2Compat, Debug) << "Servicing munmap";
 
 	auto iter = mmaps_.find(addr);
@@ -592,7 +600,8 @@ int V4L2CameraProxy::vidioc_qbuf(V4L2CameraFile *file, struct v4l2_buffer *arg)
 	return ret;
 }
 
-int V4L2CameraProxy::vidioc_dqbuf(V4L2CameraFile *file, struct v4l2_buffer *arg)
+int V4L2CameraProxy::vidioc_dqbuf(V4L2CameraFile *file,
+				  struct v4l2_buffer *arg, MutexLocker &locker)
 {
 	LOG(V4L2Compat, Debug) << "Servicing vidioc_dqbuf fd = " << file->efd();
 
@@ -609,9 +618,11 @@ int V4L2CameraProxy::vidioc_dqbuf(V4L2CameraFile *file, struct v4l2_buffer *arg)
 	    !validateMemoryType(arg->memory))
 		return -EINVAL;
 
-	if (!(file->nonBlocking()))
+	if (!(file->nonBlocking())) {
+		locker.unlock();
 		vcam_->waitForBufferAvailable();
-	else if (!vcam_->isBufferAvailable())
+		locker.lock();
+	} else if (!vcam_->isBufferAvailable())
 		return -EAGAIN;
 
 	/*
@@ -706,6 +717,8 @@ const std::set<unsigned long> V4L2CameraProxy::supportedIoctls_ = {
 
 int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long request, void *arg)
 {
+	MutexLocker locker(proxyMutex_);
+
 	if (!arg && (_IOC_DIR(request) & _IOC_WRITE)) {
 		errno = EFAULT;
 		return -1;
@@ -766,7 +779,7 @@ int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long request, void *ar
 		ret = vidioc_qbuf(file, static_cast<struct v4l2_buffer *>(arg));
 		break;
 	case VIDIOC_DQBUF:
-		ret = vidioc_dqbuf(file, static_cast<struct v4l2_buffer *>(arg));
+		ret = vidioc_dqbuf(file, static_cast<struct v4l2_buffer *>(arg), locker);
 		break;
 	case VIDIOC_STREAMON:
 		ret = vidioc_streamon(file, static_cast<int *>(arg));
diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h
index 041f536..b6d2c2c 100644
--- a/src/v4l2/v4l2_camera_proxy.h
+++ b/src/v4l2/v4l2_camera_proxy.h
@@ -61,7 +61,7 @@ private:
 	int vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuffers *arg);
 	int vidioc_querybuf(V4L2CameraFile *file, struct v4l2_buffer *arg);
 	int vidioc_qbuf(V4L2CameraFile *file, struct v4l2_buffer *arg);
-	int vidioc_dqbuf(V4L2CameraFile *file, struct v4l2_buffer *arg);
+	int vidioc_dqbuf(V4L2CameraFile *file, struct v4l2_buffer *arg, MutexLocker &locker);
 	int vidioc_streamon(V4L2CameraFile *file, int *arg);
 	int vidioc_streamoff(V4L2CameraFile *file, int *arg);
 
@@ -105,6 +105,9 @@ private:
 	 * g/s_priority, enum/g/s_input
 	 */
 	V4L2CameraFile *owner_;
+
+	/* This mutex is to serialize access to the proxy. */
+	Mutex proxyMutex_;
 };
 
 #endif /* __V4L2_CAMERA_PROXY_H__ */
-- 
2.27.0



More information about the libcamera-devel mailing list