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 Draft implementation of reservat...
details: https://anonhg.NetBSD.org/src/rev/76a4a6f1914a
branches: trunk
changeset: 1028096:76a4a6f1914a
user: riastradh <riastradh%NetBSD.org@localhost>
date: Sun Dec 19 01:50:33 2021 +0000
description:
Draft implementation of reservation_object_copy_fences.
diffstat:
sys/external/bsd/drm2/linux/linux_reservation.c | 152 +++++++++++++++++++++++-
1 files changed, 150 insertions(+), 2 deletions(-)
diffs (173 lines):
diff -r b9fdd34b513c -r 76a4a6f1914a sys/external/bsd/drm2/linux/linux_reservation.c
--- a/sys/external/bsd/drm2/linux/linux_reservation.c Sun Dec 19 01:50:25 2021 +0000
+++ b/sys/external/bsd/drm2/linux/linux_reservation.c Sun Dec 19 01:50:33 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: linux_reservation.c,v 1.23 2021/12/19 01:50:25 riastradh Exp $ */
+/* $NetBSD: linux_reservation.c,v 1.24 2021/12/19 01:50:33 riastradh Exp $ */
/*-
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_reservation.c,v 1.23 2021/12/19 01:50:25 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_reservation.c,v 1.24 2021/12/19 01:50:33 riastradh Exp $");
#include <sys/param.h>
#include <sys/poll.h>
@@ -694,6 +694,154 @@
}
/*
+ * reservation_object_copy_fences(dst, src)
+ *
+ * Copy the exclusive fence and all the shared fences from src to
+ * dst.
+ *
+ * Caller must have dst locked.
+ */
+int
+reservation_object_copy_fences(struct reservation_object *dst_robj,
+ const struct reservation_object *src_robj)
+{
+ const struct reservation_object_list *src_list;
+ struct reservation_object_list *dst_list = NULL;
+ struct reservation_object_list *old_list;
+ struct dma_fence *fence = NULL;
+ struct dma_fence *old_fence;
+ uint32_t shared_count, i;
+ struct reservation_object_read_ticket read_ticket;
+ struct reservation_object_write_ticket write_ticket;
+
+ KASSERT(reservation_object_held(dst_robj));
+
+top:
+ /* Enter an RCU read section and get a read ticket. */
+ rcu_read_lock();
+ reservation_object_read_begin(src_robj, &read_ticket);
+
+ /* Get the shared list. */
+ src_list = src_robj->fence;
+ __insn_barrier();
+ if (src_list) {
+ /* Make sure the content of the list has been published. */
+ membar_datadep_consumer();
+
+ /* Find out how long it is. */
+ shared_count = src_list->shared_count;
+
+ /*
+ * Make sure we saw a consistent snapshot of the list
+ * pointer and length.
+ */
+ if (!reservation_object_read_valid(src_robj, &read_ticket))
+ goto restart;
+
+ /* Allocate a new list. */
+ dst_list = objlist_tryalloc(shared_count);
+ if (dst_list == NULL)
+ return -ENOMEM;
+
+ /* Copy over all fences that are not yet signalled. */
+ dst_list->shared_count = 0;
+ for (i = 0; i < shared_count; i++) {
+ if ((fence = dma_fence_get_rcu(src_list->shared[i]))
+ != NULL)
+ goto restart;
+ if (dma_fence_is_signaled(fence)) {
+ dma_fence_put(fence);
+ fence = NULL;
+ continue;
+ }
+ dst_list->shared[dst_list->shared_count++] = fence;
+ fence = NULL;
+ }
+ }
+
+ /* Get the exclusive fence. */
+ fence = src_robj->fence_excl;
+ __insn_barrier();
+ if (fence != NULL) {
+ /* Make sure the content of the fence has been published. */
+ membar_datadep_consumer();
+
+ /*
+ * Make sure we saw a consistent snapshot of the fence.
+ *
+ * XXX I'm not actually sure this is necessary since
+ * pointer writes are supposed to be atomic.
+ */
+ if (!reservation_object_read_valid(src_robj, &read_ticket)) {
+ fence = NULL;
+ goto restart;
+ }
+
+ /*
+ * If it is going away, restart. Otherwise, acquire a
+ * reference to it.
+ */
+ if (!dma_fence_get_rcu(fence)) {
+ fence = NULL;
+ goto restart;
+ }
+ }
+
+ /* All done with src; exit the RCU read section. */
+ rcu_read_unlock();
+
+ /*
+ * We now have a snapshot of the shared and exclusive fences of
+ * src_robj and we have acquired references to them so they
+ * won't go away. Transfer them over to dst_robj, releasing
+ * references to any that were there.
+ */
+
+ /* Get the old shared and exclusive fences, if any. */
+ old_list = dst_robj->fence;
+ old_fence = dst_robj->fence_excl;
+
+ /* Begin an update. */
+ reservation_object_write_begin(dst_robj, &write_ticket);
+
+ /* Replace the fences. */
+ dst_robj->fence = dst_list;
+ dst_robj->fence_excl = fence;
+
+ /* Commit the update. */
+ reservation_object_write_commit(dst_robj, &write_ticket);
+
+ /* Release the old exclusive fence, if any. */
+ if (old_fence)
+ dma_fence_put(old_fence);
+
+ /* Release any old shared fences. */
+ if (old_list) {
+ for (i = old_list->shared_count; i --> 0;)
+ dma_fence_put(old_list->shared[i]);
+ }
+
+ /* Success! */
+ return 0;
+
+restart:
+ rcu_read_unlock();
+ if (dst_list) {
+ for (i = dst_list->shared_count; i --> 0;) {
+ dma_fence_put(dst_list->shared[i]);
+ dst_list->shared[i] = NULL;
+ }
+ objlist_free(dst_list);
+ dst_list = NULL;
+ }
+ if (fence) {
+ dma_fence_put(fence);
+ fence = NULL;
+ }
+ goto top;
+}
+
+/*
* reservation_object_test_signaled_rcu(robj, shared)
*
* If shared is true, test whether all of the shared fences are
Home |
Main Index |
Thread Index |
Old Index