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 <paul.elder@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
12fa2fe020
commit
0952f2014d
2 changed files with 21 additions and 5 deletions
|
@ -45,6 +45,8 @@ int V4L2CameraProxy::open(V4L2CameraFile *file)
|
||||||
{
|
{
|
||||||
LOG(V4L2Compat, Debug) << "Servicing open fd = " << file->efd();
|
LOG(V4L2Compat, Debug) << "Servicing open fd = " << file->efd();
|
||||||
|
|
||||||
|
MutexLocker locker(proxyMutex_);
|
||||||
|
|
||||||
if (refcount_++) {
|
if (refcount_++) {
|
||||||
files_.insert(file);
|
files_.insert(file);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -79,6 +81,8 @@ void V4L2CameraProxy::close(V4L2CameraFile *file)
|
||||||
{
|
{
|
||||||
LOG(V4L2Compat, Debug) << "Servicing close fd = " << file->efd();
|
LOG(V4L2Compat, Debug) << "Servicing close fd = " << file->efd();
|
||||||
|
|
||||||
|
MutexLocker locker(proxyMutex_);
|
||||||
|
|
||||||
files_.erase(file);
|
files_.erase(file);
|
||||||
|
|
||||||
release(file);
|
release(file);
|
||||||
|
@ -94,6 +98,8 @@ void *V4L2CameraProxy::mmap(void *addr, size_t length, int prot, int flags,
|
||||||
{
|
{
|
||||||
LOG(V4L2Compat, Debug) << "Servicing mmap";
|
LOG(V4L2Compat, Debug) << "Servicing mmap";
|
||||||
|
|
||||||
|
MutexLocker locker(proxyMutex_);
|
||||||
|
|
||||||
/* \todo Validate prot and flags properly. */
|
/* \todo Validate prot and flags properly. */
|
||||||
if (prot != (PROT_READ | PROT_WRITE)) {
|
if (prot != (PROT_READ | PROT_WRITE)) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
|
@ -128,6 +134,8 @@ int V4L2CameraProxy::munmap(void *addr, size_t length)
|
||||||
{
|
{
|
||||||
LOG(V4L2Compat, Debug) << "Servicing munmap";
|
LOG(V4L2Compat, Debug) << "Servicing munmap";
|
||||||
|
|
||||||
|
MutexLocker locker(proxyMutex_);
|
||||||
|
|
||||||
auto iter = mmaps_.find(addr);
|
auto iter = mmaps_.find(addr);
|
||||||
if (iter == mmaps_.end() || length != sizeimage_) {
|
if (iter == mmaps_.end() || length != sizeimage_) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
|
@ -587,7 +595,8 @@ int V4L2CameraProxy::vidioc_qbuf(V4L2CameraFile *file, struct v4l2_buffer *arg)
|
||||||
return ret;
|
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();
|
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))
|
!validateMemoryType(arg->memory))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!file->nonBlocking())
|
if (!file->nonBlocking()) {
|
||||||
|
locker->unlock();
|
||||||
vcam_->waitForBufferAvailable();
|
vcam_->waitForBufferAvailable();
|
||||||
else if (!vcam_->isBufferAvailable())
|
locker->lock();
|
||||||
|
} else if (!vcam_->isBufferAvailable())
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -701,6 +712,8 @@ const std::set<unsigned long> V4L2CameraProxy::supportedIoctls_ = {
|
||||||
|
|
||||||
int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long request, void *arg)
|
int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long request, void *arg)
|
||||||
{
|
{
|
||||||
|
MutexLocker locker(proxyMutex_);
|
||||||
|
|
||||||
if (!arg && (_IOC_DIR(request) & _IOC_WRITE)) {
|
if (!arg && (_IOC_DIR(request) & _IOC_WRITE)) {
|
||||||
errno = EFAULT;
|
errno = EFAULT;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -761,7 +774,7 @@ int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long request, void *ar
|
||||||
ret = vidioc_qbuf(file, static_cast<struct v4l2_buffer *>(arg));
|
ret = vidioc_qbuf(file, static_cast<struct v4l2_buffer *>(arg));
|
||||||
break;
|
break;
|
||||||
case VIDIOC_DQBUF:
|
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;
|
break;
|
||||||
case VIDIOC_STREAMON:
|
case VIDIOC_STREAMON:
|
||||||
ret = vidioc_streamon(file, static_cast<int *>(arg));
|
ret = vidioc_streamon(file, static_cast<int *>(arg));
|
||||||
|
|
|
@ -61,7 +61,7 @@ private:
|
||||||
int vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuffers *arg);
|
int vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuffers *arg);
|
||||||
int vidioc_querybuf(V4L2CameraFile *file, struct v4l2_buffer *arg);
|
int vidioc_querybuf(V4L2CameraFile *file, struct v4l2_buffer *arg);
|
||||||
int vidioc_qbuf(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_streamon(V4L2CameraFile *file, int *arg);
|
||||||
int vidioc_streamoff(V4L2CameraFile *file, int *arg);
|
int vidioc_streamoff(V4L2CameraFile *file, int *arg);
|
||||||
|
|
||||||
|
@ -105,6 +105,9 @@ private:
|
||||||
* will return -EBUSY.
|
* will return -EBUSY.
|
||||||
*/
|
*/
|
||||||
V4L2CameraFile *owner_;
|
V4L2CameraFile *owner_;
|
||||||
|
|
||||||
|
/* This mutex is to serialize access to the proxy. */
|
||||||
|
Mutex proxyMutex_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __V4L2_CAMERA_PROXY_H__ */
|
#endif /* __V4L2_CAMERA_PROXY_H__ */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue