From: Mauro Carvalho Chehab <mchehab@redhat.com>
To: Hans Verkuil <hverkuil@xs4all.nl>
Cc: linux-media@vger.kernel.org, Arnd Bergmann <arnd@arndb.de>
Subject: Re: [RFC PATCHES] First version of the V4L2 core locking patches
Date: Tue, 21 Sep 2010 10:40:51 -0300 [thread overview]
Message-ID: <4C98B5E3.9010008@redhat.com> (raw)
In-Reply-To: <201009202337.01948.hverkuil@xs4all.nl>
Em 20-09-2010 18:37, Hans Verkuil escreveu:
> Hi all,
>
> I've made a first version of the core locking patches available here:
>
> http://git.linuxtv.org/hverkuil/v4l-dvb.git?a=shortlog;h=refs/heads/test
>
> I'm actually surprised how trivial the patches are. Which makes me wonder if
> I am overlooking something, it feels too easy.
>
> One thing I did not yet have time to analyze fully is if it is really OK to
> unlock/relock the vdev_lock in videobuf_waiton. I hope it is, because without
> this another thread will find it impossible to access the video node while it
> is in waiton.
>
> Currently I've only tested with vivi. I hope to be able to spend more time
> this week for a more thorough analysis and converting a few more drivers to
> this.
>
> In the meantime, please feel free to shoot at this code!
Hi Hans,
This patch will likely break most drivers:
http://git.linuxtv.org/hverkuil/v4l-dvb.git?a=commitdiff;h=d1ca35f3e69d909a958eb1cf8c75dd1c0bb2a98c
In the case of events and videobuf_waiton, it doesn't seem to be safe to just
unlock when waiting for an event.
For example, in the case of videobuf_waiton, the code for it is:
#define WAITON_CONDITION (vb->state != VIDEOBUF_ACTIVE &&\
vb->state != VIDEOBUF_QUEUED)
int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr)
{
MAGIC_CHECK(vb->magic, MAGIC_BUFFER);
if (non_blocking) {
if (WAITON_CONDITION)
return 0;
else
return -EAGAIN;
}
if (intr)
return wait_event_interruptible(vb->done, WAITON_CONDITION);
else
wait_event(vb->done, WAITON_CONDITION);
return 0;
}
When called internally, it have the vb mutex_locked, while, when called externally, it
doesn't.
By looking on other parts where vb->done is protected, like on videobuf_queue_cancel:
spin_lock_irqsave(q->irqlock, flags);
for (i = 0; i < VIDEO_MAX_FRAME; i++) {
if (NULL == q->bufs[i])
continue;
if (q->bufs[i]->state == VIDEOBUF_QUEUED) {
list_del(&q->bufs[i]->queue);
q->bufs[i]->state = VIDEOBUF_ERROR;
wake_up_all(&q->bufs[i]->done);
}
}
spin_unlock_irqrestore(q->irqlock, flags);
It is clear that vb state is protected by a spinlock, and not by a mutex. Using a mutex
there makes no sense at all. Instead of touching a mutex, callers of this function should
be reviewed to not call a mutex.
So, the better approach for videobuf_waiton would be to protect it with a
spinlock.
Also, your patches assume that no driver will touch at vdev lock before calling videobuf_waiton().
This seems to be a risky assumption. So, the better would be to define it as:
static int is_state_active_or_queued(struct videobuf_buffer *vb, struct videobuf_queue *q, )
{
bool rc;
spin_lock_irqsave(q->irqlock, flags);
rc = (vb->state != VIDEOBUF_ACTIVE) && (vb->state != VIDEOBUF_QUEUED));
spin_unlock_irqrestore(q->irqlock, flags);
return rc;
};
int videobuf_waiton(struct videobuf_queue *q, struct videobuf_buffer *vb, int non_blocking, int intr)
{
rc = 0;
bool is_vdev_locked;
MAGIC_CHECK(vb->magic, MAGIC_BUFFER);
/*
* If there's nothing to wait, just return
*/
if (is_state_active_or_queued(vb, q))
return 0;
if (non_blocking)
return -EAGAIN;
/*
* Need to sleep in order to wait for videobufs to complete.
* It is not a good idea to sleep while waiting for an event with the dev lock hold,
* as it will block any other access to the device. Just unlock it while waiting,
* locking it again at the end.
*/
is_vdev_locked = (q->vdev_lock && mutex_is_locked(q->vdev_lock)) ? true : false;
if (is_vdev_locked)
mutex_unlock(q->vdev_lock);
if (intr)
return wait_event_interruptible(vb->done, is_state_active_or_queued(vb, q));
else
wait_event(vb->done, is_state_active_or_queued(vb, q));
if (is_vdev_locked)
mutex_lock(q->vdev_lock);
return 0;
}
Cheers,
Mauro
next prev parent reply other threads:[~2010-09-21 13:41 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-09-20 21:37 [RFC PATCHES] First version of the V4L2 core locking patches Hans Verkuil
2010-09-21 13:40 ` Mauro Carvalho Chehab [this message]
2010-09-21 13:50 ` Hans Verkuil
2010-09-21 17:14 ` Mauro Carvalho Chehab
2010-09-21 19:04 ` Hans Verkuil
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4C98B5E3.9010008@redhat.com \
--to=mchehab@redhat.com \
--cc=arnd@arndb.de \
--cc=hverkuil@xs4all.nl \
--cc=linux-media@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.