From: Daniel Vetter <daniel@ffwll.ch>
To: Ilija Hadzic <ihadzic@research.bell-labs.com>
Cc: dri-devel@lists.freedesktop.org
Subject: Re: [PATCH 3/3] drm: do not sleep on vblank while holding a mutex
Date: Wed, 26 Oct 2011 09:54:01 +0200 [thread overview]
Message-ID: <20111026075401.GD2889@phenom.ffwll.local> (raw)
In-Reply-To: <1319595614-9098-4-git-send-email-ihadzic@research.bell-labs.com>
On Tue, Oct 25, 2011 at 10:20:14PM -0400, Ilija Hadzic wrote:
> holding the drm_global_mutex in drm_wait_vblank and then
> going to sleep (via DRM_WAIT_ON) is a bad idea in general
> because it can block other processes that may issue ioctls
> that also grab drm_global_mutex. Blocking can occur until
> next vblank which is in the tens of microseconds order of
> magnitude.
>
> fix it, but making drm_wait_vblank DRM_UNLOCKED call and
> then grabbing the mutex inside the drm_wait_vblank function
> and only for the duration of the critical section (i.e.,
> from first manipulation of vblank sequence number until
> putting the task in the wait queue).
>
> Signed-off-by: Ilija Hadzic <ihadzic@research.bell-labs.com>
While you mess around with this code, please use the standard linux
wait_event_* infrastructure. I want to stop that DRM_FOO yelling from
spreading around - the idea of the drm core being os agnostic died quite a
while ago.
Again, have you carefully checked whether this is safe and how the
relevant data structures (vblank counting) are proctected?
One comment below, mind though that I've only glanced over the patch.
-Daniel
> ---
> drivers/gpu/drm/drm_drv.c | 2 +-
> drivers/gpu/drm/drm_irq.c | 16 +++++++++++-----
> include/drm/drm_os_linux.h | 25 +++++++++++++++++++++++++
> 3 files changed, 37 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> index dbabcb0..dc0eb0b 100644
> --- a/drivers/gpu/drm/drm_drv.c
> +++ b/drivers/gpu/drm/drm_drv.c
> @@ -124,7 +124,7 @@ static struct drm_ioctl_desc drm_ioctls[] = {
> DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
>
> - DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
> + DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED),
>
> DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
>
> diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
> index 3830e9e..d85d604 100644
> --- a/drivers/gpu/drm/drm_irq.c
> +++ b/drivers/gpu/drm/drm_irq.c
> @@ -1191,6 +1191,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
> DRM_DEBUG("failed to acquire vblank counter, %d\n", ret);
> return ret;
> }
> + mutex_lock(&drm_global_mutex);
> seq = drm_vblank_count(dev, crtc);
>
> switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
> @@ -1200,12 +1201,15 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
> case _DRM_VBLANK_ABSOLUTE:
> break;
> default:
> + mutex_unlock(&drm_global_mutex);
> ret = -EINVAL;
> goto done;
> }
>
> - if (flags & _DRM_VBLANK_EVENT)
> + if (flags & _DRM_VBLANK_EVENT) {
> + mutex_unlock(&drm_global_mutex);
> return drm_queue_vblank_event(dev, crtc, vblwait, file_priv);
> + }
>
> if ((flags & _DRM_VBLANK_NEXTONMISS) &&
> (seq - vblwait->request.sequence) <= (1<<23)) {
> @@ -1215,10 +1219,12 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
> DRM_DEBUG("waiting on vblank count %d, crtc %d\n",
> vblwait->request.sequence, crtc);
> dev->last_vblank_wait[crtc] = vblwait->request.sequence;
> - DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
> - (((drm_vblank_count(dev, crtc) -
> - vblwait->request.sequence) <= (1 << 23)) ||
> - !dev->irq_enabled));
> + /* DRM_WAIT_ON_LOCKED will release drm_global_mutex */
> + /* before going to sleep */
> + DRM_WAIT_ON_LOCKED(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
> + (((drm_vblank_count(dev, crtc) -
> + vblwait->request.sequence) <= (1 << 23)) ||
> + !dev->irq_enabled));
>
> if (ret != -EINTR) {
> struct timeval now;
> diff --git a/include/drm/drm_os_linux.h b/include/drm/drm_os_linux.h
> index 3933691..fc6aaf4 100644
> --- a/include/drm/drm_os_linux.h
> +++ b/include/drm/drm_os_linux.h
> @@ -123,5 +123,30 @@ do { \
> remove_wait_queue(&(queue), &entry); \
> } while (0)
>
> +#define DRM_WAIT_ON_LOCKED( ret, queue, timeout, condition ) \
> +do { \
> + DECLARE_WAITQUEUE(entry, current); \
> + unsigned long end = jiffies + (timeout); \
> + add_wait_queue(&(queue), &entry); \
> + mutex_unlock(&drm_global_mutex); \
Hiding a lock-dropping in this fashion is horrible.
> + \
> + for (;;) { \
> + __set_current_state(TASK_INTERRUPTIBLE); \
> + if (condition) \
> + break; \
> + if (time_after_eq(jiffies, end)) { \
> + ret = -EBUSY; \
> + break; \
> + } \
> + schedule_timeout((HZ/100 > 1) ? HZ/100 : 1); \
> + if (signal_pending(current)) { \
> + ret = -EINTR; \
> + break; \
> + } \
> + } \
> + __set_current_state(TASK_RUNNING); \
> + remove_wait_queue(&(queue), &entry); \
> +} while (0)
> +
> #define DRM_WAKEUP( queue ) wake_up( queue )
> #define DRM_INIT_WAITQUEUE( queue ) init_waitqueue_head( queue )
> --
> 1.7.7
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
--
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48
next prev parent reply other threads:[~2011-10-26 7:53 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-10-26 2:20 drm: fix one flawed mutex grab and remove some spurious mutex grabs Ilija Hadzic
2011-10-26 2:20 ` [PATCH 1/3] drm: no need to hold global mutex for static data Ilija Hadzic
2011-10-26 7:44 ` Daniel Vetter
2011-10-26 2:20 ` [PATCH 2/3] drm: make DRM_UNLOCKED ioctls with their own mutex Ilija Hadzic
2011-10-26 7:47 ` Daniel Vetter
2011-10-26 16:11 ` Ilija Hadzic
2011-10-26 20:01 ` Daniel Vetter
2011-10-26 2:20 ` [PATCH 3/3] drm: do not sleep on vblank while holding a mutex Ilija Hadzic
2011-10-26 7:54 ` Daniel Vetter [this message]
2011-10-26 22:33 ` Ilija Hadzic
2011-10-27 10:43 ` Daniel Vetter
2011-10-27 14:10 ` Alan Coopersmith
2011-10-27 14:20 ` Ilija Hadzic
2011-10-28 3:19 ` Ilija Hadzic
2011-10-28 4:36 ` Ilija Hadzic
2011-10-28 6:59 ` Michel Dänzer
2011-10-28 9:20 ` Daniel Vetter
2011-10-28 12:10 ` Ilija Hadzic
2011-10-28 14:51 ` Daniel Vetter
2011-10-28 9:30 ` Daniel Vetter
2011-10-26 8:02 ` Michel Dänzer
2011-10-26 22:50 ` Ilija Hadzic
[not found] <mailman.37.1319803862.23620.dri-devel@lists.freedesktop.org>
2011-10-28 18:15 ` Mario Kleiner
2011-10-28 19:15 ` Daniel Vetter
2011-10-28 19:53 ` Mario Kleiner
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=20111026075401.GD2889@phenom.ffwll.local \
--to=daniel@ffwll.ch \
--cc=dri-devel@lists.freedesktop.org \
--cc=ihadzic@research.bell-labs.com \
/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.