Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/external/bsd/drm2/drm Serialize drm_read so we can back ...
details: https://anonhg.NetBSD.org/src/rev/c5087fa144c1
branches: trunk
changeset: 1027855:c5087fa144c1
user: riastradh <riastradh%NetBSD.org@localhost>
date: Sun Dec 19 00:58:11 2021 +0000
description:
Serialize drm_read so we can back out on uiomove without reordering.
Upstream commit 9b2c0b7fb4ce79566d830d03ce7aa11cccc39f97.
diffstat:
sys/external/bsd/drm2/drm/drm_cdevsw.c | 88 ++++++++++++++++++++++++++++-----
1 files changed, 74 insertions(+), 14 deletions(-)
diffs (133 lines):
diff -r 18f5db9ae60b -r c5087fa144c1 sys/external/bsd/drm2/drm/drm_cdevsw.c
--- a/sys/external/bsd/drm2/drm/drm_cdevsw.c Sun Dec 19 00:58:04 2021 +0000
+++ b/sys/external/bsd/drm2/drm/drm_cdevsw.c Sun Dec 19 00:58:11 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: drm_cdevsw.c,v 1.19 2021/12/19 00:48:45 riastradh Exp $ */
+/* $NetBSD: drm_cdevsw.c,v 1.20 2021/12/19 00:58:11 riastradh Exp $ */
/*-
* Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: drm_cdevsw.c,v 1.19 2021/12/19 00:48:45 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: drm_cdevsw.c,v 1.20 2021/12/19 00:58:11 riastradh Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -274,35 +274,82 @@
int flags)
{
struct drm_file *const file = fp->f_data;
+ struct drm_device *const dev = file->minor->dev;
struct drm_pending_event *event;
bool first;
- int error = 0;
+ int ret = 0;
+
+ /*
+ * Only one event reader at a time, so that if copyout faults
+ * after dequeueing one event and we have to put the event
+ * back, another reader won't see out-of-order events.
+ */
+ spin_lock(&dev->event_lock);
+ DRM_SPIN_WAIT_NOINTR_UNTIL(ret, &file->event_read_wq, &dev->event_lock,
+ file->event_read_lock == NULL);
+ if (ret) {
+ spin_unlock(&dev->event_lock);
+ /* XXX errno Linux->NetBSD */
+ return -ret;
+ }
+ file->event_read_lock = curlwp;
+ spin_unlock(&dev->event_lock);
for (first = true; ; first = false) {
int f = 0;
+ off_t offset;
+ size_t resid;
if (!first || ISSET(fp->f_flag, FNONBLOCK))
f |= FNONBLOCK;
- /* XXX errno Linux->NetBSD */
- error = -drm_dequeue_event(file, uio->uio_resid, &event, f);
- if (error) {
- if ((error == EWOULDBLOCK) && !first)
- error = 0;
+ ret = drm_dequeue_event(file, uio->uio_resid, &event, f);
+ if (ret) {
+ if ((ret == -EWOULDBLOCK) && !first)
+ ret = 0;
break;
}
if (event == NULL)
break;
- error = uiomove(event->event, event->event->length, uio);
- if (error) /* XXX Requeue the event? */
+
+ offset = uio->uio_offset;
+ resid = uio->uio_resid;
+ /* XXX errno NetBSD->Linux */
+ ret = -uiomove(event->event, event->event->length, uio);
+ if (ret) {
+ /*
+ * Faulted on copyout. Put the event back and
+ * stop here.
+ */
+ if (!first) {
+ /*
+ * Already transferred some events.
+ * Rather than back them all out, just
+ * say we succeeded at returning those.
+ */
+ ret = 0;
+ }
+ uio->uio_offset = offset;
+ uio->uio_resid = resid;
+ drm_requeue_event(file, event);
break;
- (*event->destroy)(event);
+ }
+ kfree(event);
}
+ /* Release the event read lock. */
+ spin_lock(&dev->event_lock);
+ KASSERT(file->event_read_lock == curlwp);
+ file->event_read_lock = NULL;
+ DRM_SPIN_WAKEUP_ONE(&file->event_read_wq, &dev->event_lock);
+ spin_unlock(&dev->event_lock);
+
+ /* XXX errno Linux->NetBSD */
+
/* Success! */
- if (error == ERESTARTSYS)
- error = ERESTART;
- return error;
+ if (ret == ERESTARTSYS)
+ ret = ERESTART;
+ return -ret;
}
static int
@@ -343,6 +390,19 @@
return ret;
}
+static void
+drm_requeue_event(struct drm_file *file, struct drm_pending_event *event)
+{
+ struct drm_device *const dev = file->minor->dev;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dev->event_lock, irqflags);
+ list_add(&event->link, &file->event_list);
+ KASSERT(file->event_space >= event->event->length);
+ file->event_space -= event->event->length;
+ spin_unlock_irqrestore(&dev->event_lock, irqflags);
+}
+
static int
drm_ioctl_shim(struct file *fp, unsigned long cmd, void *data)
{
Home |
Main Index |
Thread Index |
Old Index