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/linux drm: Rework dma_fence_wait_any_t...
details: https://anonhg.NetBSD.org/src/rev/12941098fe0e
branches: trunk
changeset: 1028952:12941098fe0e
user: riastradh <riastradh%NetBSD.org@localhost>
date: Sun Dec 19 12:34:05 2021 +0000
description:
drm: Rework dma_fence_wait_any_timeout.
- Yield the first index, not the most recently signalled one.
- Check again after last wakeup.
- Make sure to return positive for nontimeout.
- Handle ip=null.
diffstat:
sys/external/bsd/drm2/linux/linux_dma_fence.c | 86 +++++++++++++++-----------
1 files changed, 50 insertions(+), 36 deletions(-)
diffs (169 lines):
diff -r bb3f96016128 -r 12941098fe0e sys/external/bsd/drm2/linux/linux_dma_fence.c
--- a/sys/external/bsd/drm2/linux/linux_dma_fence.c Sun Dec 19 12:33:56 2021 +0000
+++ b/sys/external/bsd/drm2/linux/linux_dma_fence.c Sun Dec 19 12:34:05 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: linux_dma_fence.c,v 1.30 2021/12/19 12:31:11 riastradh Exp $ */
+/* $NetBSD: linux_dma_fence.c,v 1.31 2021/12/19 12:34:05 riastradh Exp $ */
/*-
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_dma_fence.c,v 1.30 2021/12/19 12:31:11 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_dma_fence.c,v 1.31 2021/12/19 12:34:05 riastradh Exp $");
#include <sys/atomic.h>
#include <sys/condvar.h>
@@ -685,9 +685,8 @@
struct wait_any1 {
kmutex_t lock;
kcondvar_t cv;
+ struct wait_any *cb;
bool done;
- uint32_t *ip;
- struct wait_any *cb;
} *common;
};
@@ -700,8 +699,6 @@
mutex_enter(&cb->common->lock);
cb->common->done = true;
- if (cb->common->ip)
- *cb->common->ip = cb - cb->common->cb;
cv_broadcast(&cb->common->cv);
mutex_exit(&cb->common->lock);
}
@@ -712,6 +709,9 @@
* Wait for any of fences[0], fences[1], fences[2], ...,
* fences[nfences-1] to be signalled. If ip is nonnull, set *ip
* to the index of the first one.
+ *
+ * Return -ERESTARTSYS if interrupted, 0 on timeout, or time
+ * remaining (at least 1) on success.
*/
long
dma_fence_wait_any_timeout(struct dma_fence **fences, uint32_t nfences,
@@ -723,6 +723,22 @@
int start, end;
long ret = 0;
+ /* Optimistically check whether any are signalled. */
+ for (i = 0; i < nfences; i++) {
+ if (dma_fence_is_signaled(fences[i])) {
+ if (ip)
+ *ip = i;
+ return MAX(1, timeout);
+ }
+ }
+
+ /*
+ * If timeout is zero, we're just polling, so stop here as if
+ * we timed out instantly.
+ */
+ if (timeout == 0)
+ return 0;
+
/* Allocate an array of callback records. */
cb = kcalloc(nfences, sizeof(cb[0]), GFP_KERNEL);
if (cb == NULL) {
@@ -733,30 +749,23 @@
/* Initialize a mutex and condvar for the common wait. */
mutex_init(&common.lock, MUTEX_DEFAULT, IPL_VM);
cv_init(&common.cv, "fence");
+ common.cb = cb;
common.done = false;
- common.ip = ip;
- common.cb = cb;
- /* Add a callback to each of the fences, or stop here if we can't. */
+ /*
+ * Add a callback to each of the fences, or stop if already
+ * signalled.
+ */
for (i = 0; i < nfences; i++) {
cb[i].common = &common;
KASSERT(dma_fence_referenced_p(fences[i]));
ret = dma_fence_add_callback(fences[i], &cb[i].fcb,
&wait_any_cb);
- if (ret)
- goto out1;
- }
-
- /*
- * Test whether any of the fences has been signalled. If they
- * have, stop here. If the haven't, we are guaranteed to be
- * notified by one of the callbacks when they have.
- */
- for (j = 0; j < nfences; j++) {
- if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fences[j]->flags)) {
+ if (ret) {
+ KASSERT(ret == -ENOENT);
if (ip)
- *ip = j;
- ret = 0;
+ *ip = i;
+ ret = MAX(1, timeout);
goto out1;
}
}
@@ -768,7 +777,6 @@
mutex_enter(&common.lock);
while (timeout > 0 && !common.done) {
start = getticks();
- __insn_barrier();
if (intr) {
if (timeout != MAX_SCHEDULE_TIMEOUT) {
ret = -cv_timedwait_sig(&common.cv,
@@ -788,30 +796,36 @@
}
}
end = getticks();
- __insn_barrier();
- if (ret) {
- if (ret == -ERESTART)
- ret = -ERESTARTSYS;
+ if (ret)
break;
- }
timeout -= MIN(timeout, (unsigned)end - (unsigned)start);
}
mutex_exit(&common.lock);
/*
+ * Test whether any of the fences has been signalled. If they
+ * have, return success.
+ */
+ for (j = 0; j < nfences; j++) {
+ if (dma_fence_is_signaled(fences[i])) {
+ if (ip)
+ *ip = j;
+ ret = MAX(1, timeout);
+ goto out1;
+ }
+ }
+
+ /*
* Massage the return code: if we were interrupted, return
* ERESTARTSYS; if cv_timedwait timed out, return 0; otherwise
* return the remaining time.
*/
- if (ret < 0) {
- if (ret == -EINTR || ret == -ERESTART)
- ret = -ERESTARTSYS;
- if (ret == -EWOULDBLOCK)
- ret = 0;
- } else {
- KASSERT(ret == 0);
- ret = timeout;
+ if (ret == -EINTR || ret == -ERESTART) {
+ ret = -ERESTARTSYS;
+ } else if (ret == -EWOULDBLOCK) {
+ ret = 0; /* timed out */
}
+ KASSERTMSG(ret == -ERESTARTSYS || ret >= 0, "ret=%ld", ret);
out1: while (i --> 0)
(void)dma_fence_remove_callback(fences[i], &cb[i].fcb);
Home |
Main Index |
Thread Index |
Old Index