From 0952f2014d1f08d1e5228f90680af16cb66653a6 Mon Sep 17 00:00:00 2001 From: Paul Elder Date: Wed, 24 Jun 2020 02:41:18 +0900 Subject: v4l2: v4l2_camera_proxy: Serialize accesses to the proxy 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 Reviewed-by: Laurent Pinchart --- src/v4l2/v4l2_camera_proxy.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'src/v4l2/v4l2_camera_proxy.cpp') diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index 7579d93b..c2465701 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; @@ -587,7 +595,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(); @@ -604,9 +613,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; /* @@ -701,6 +712,8 @@ const std::set 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; @@ -761,7 +774,7 @@ int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long request, void *ar ret = vidioc_qbuf(file, static_cast(arg)); break; case VIDIOC_DQBUF: - ret = vidioc_dqbuf(file, static_cast(arg)); + ret = vidioc_dqbuf(file, static_cast(arg), &locker); break; case VIDIOC_STREAMON: ret = vidioc_streamon(file, static_cast(arg)); -- cgit v1.2.1