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

Paul Elder paul.elder at ideasonboard.com
Wed Jun 24 16:52:56 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>
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>

---
Changes in v4:
- cosmetic changes

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 3b7a6f4..6896e55 100644
--- a/src/v4l2/v4l2_camera_proxy.cpp
+++ b/src/v4l2/v4l2_camera_proxy.cpp
@@ -45,6 +45,8 @@ int V4L2CameraProxy::open(V4L2CameraFile *file)
 {
 	LOG(V4L2Compat, Debug) << "Servicing open fd = " << file->efd();
 
+	MutexLocker locker(proxyMutex_);
+
 	if (refcount_++) {
 		files_.insert(file);
 		return 0;
@@ -79,6 +81,8 @@ void V4L2CameraProxy::close(V4L2CameraFile *file)
 {
 	LOG(V4L2Compat, Debug) << "Servicing close fd = " << file->efd();
 
+	MutexLocker locker(proxyMutex_);
+
 	files_.erase(file);
 
 	release(file);
@@ -94,6 +98,8 @@ void *V4L2CameraProxy::mmap(void *addr, size_t length, int prot, int flags,
 {
 	LOG(V4L2Compat, Debug) << "Servicing mmap";
 
+	MutexLocker locker(proxyMutex_);
+
 	/* \todo Validate prot and flags properly. */
 	if (prot != (PROT_READ | PROT_WRITE)) {
 		errno = EINVAL;
@@ -128,6 +134,8 @@ int V4L2CameraProxy::munmap(void *addr, size_t length)
 {
 	LOG(V4L2Compat, Debug) << "Servicing munmap";
 
+	MutexLocker locker(proxyMutex_);
+
 	auto iter = mmaps_.find(addr);
 	if (iter == mmaps_.end() || length != sizeimage_) {
 		errno = EINVAL;
@@ -589,7 +597,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();
 
@@ -606,9 +615,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;
 
 	/*
@@ -703,6 +714,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;
@@ -763,7 +776,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 5de2c5a..d78a472 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:
 	 * will return -EBUSY.
 	 */
 	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