提交 9b2c0b7f 编写于 作者: C Chris Wilson 提交者: Daniel Vetter

drm: Serialise multiple event readers

The previous patch reintroduced a race condition whereby a failure in
one reader may allow a second reader to see out-of-order events.
Introduce a mutex to serialise readers so that an event is completed in
its entirety before another reader may process an event. The two readers
may race against each other, but the events each retrieves are in the
correct order.
Signed-off-by: NChris Wilson <chris@chris-wilson.co.uk>
Cc: Thomas Hellstrom <thellstrom@vmware.com>
Cc: Takashi Iwai <tiwai@suse.de>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1448462343-2072-2-git-send-email-chris@chris-wilson.co.ukReviewed-by: NThomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: NDaniel Vetter <daniel.vetter@ffwll.ch>
上级 83eb64c8
...@@ -172,6 +172,8 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor) ...@@ -172,6 +172,8 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
init_waitqueue_head(&priv->event_wait); init_waitqueue_head(&priv->event_wait);
priv->event_space = 4096; /* set aside 4k for event buffer */ priv->event_space = 4096; /* set aside 4k for event buffer */
mutex_init(&priv->event_read_lock);
if (drm_core_check_feature(dev, DRIVER_GEM)) if (drm_core_check_feature(dev, DRIVER_GEM))
drm_gem_open(dev, priv); drm_gem_open(dev, priv);
...@@ -483,11 +485,15 @@ ssize_t drm_read(struct file *filp, char __user *buffer, ...@@ -483,11 +485,15 @@ ssize_t drm_read(struct file *filp, char __user *buffer,
{ {
struct drm_file *file_priv = filp->private_data; struct drm_file *file_priv = filp->private_data;
struct drm_device *dev = file_priv->minor->dev; struct drm_device *dev = file_priv->minor->dev;
ssize_t ret = 0; ssize_t ret;
if (!access_ok(VERIFY_WRITE, buffer, count)) if (!access_ok(VERIFY_WRITE, buffer, count))
return -EFAULT; return -EFAULT;
ret = mutex_lock_interruptible(&file_priv->event_read_lock);
if (ret)
return ret;
for (;;) { for (;;) {
struct drm_pending_event *e = NULL; struct drm_pending_event *e = NULL;
...@@ -509,12 +515,13 @@ ssize_t drm_read(struct file *filp, char __user *buffer, ...@@ -509,12 +515,13 @@ ssize_t drm_read(struct file *filp, char __user *buffer,
break; break;
} }
mutex_unlock(&file_priv->event_read_lock);
ret = wait_event_interruptible(file_priv->event_wait, ret = wait_event_interruptible(file_priv->event_wait,
!list_empty(&file_priv->event_list)); !list_empty(&file_priv->event_list));
if (ret < 0) if (ret >= 0)
break; ret = mutex_lock_interruptible(&file_priv->event_read_lock);
if (ret)
ret = 0; return ret;
} else { } else {
unsigned length = e->event->length; unsigned length = e->event->length;
...@@ -537,6 +544,7 @@ ssize_t drm_read(struct file *filp, char __user *buffer, ...@@ -537,6 +544,7 @@ ssize_t drm_read(struct file *filp, char __user *buffer,
e->destroy(e); e->destroy(e);
} }
} }
mutex_unlock(&file_priv->event_read_lock);
return ret; return ret;
} }
......
...@@ -344,6 +344,8 @@ struct drm_file { ...@@ -344,6 +344,8 @@ struct drm_file {
struct list_head event_list; struct list_head event_list;
int event_space; int event_space;
struct mutex event_read_lock;
struct drm_prime_file_private prime; struct drm_prime_file_private prime;
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册