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 +++++++++++++++++---- src/v4l2/v4l2_camera_proxy.h | 5 ++++- 2 files changed, 21 insertions(+), 5 deletions(-) (limited to 'src/v4l2') 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)); diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h index 5de2c5ae..d78a4723 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__ */ -- cgit v1.2.1