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 Draft reservation_object_get_fences_rcu.
details: https://anonhg.NetBSD.org/src/rev/d3c1d640fde5
branches: trunk
changeset: 366225:d3c1d640fde5
user: riastradh <riastradh%NetBSD.org@localhost>
date: Mon Aug 27 14:01:14 2018 +0000
description:
Draft reservation_object_get_fences_rcu.
diffstat:
sys/external/bsd/drm2/include/linux/reservation.h | 7 +-
sys/external/bsd/drm2/linux/linux_reservation.c | 128 +++++++++++++++++++++-
2 files changed, 132 insertions(+), 3 deletions(-)
diffs (177 lines):
diff -r cac9419cbb75 -r d3c1d640fde5 sys/external/bsd/drm2/include/linux/reservation.h
--- a/sys/external/bsd/drm2/include/linux/reservation.h Mon Aug 27 14:01:01 2018 +0000
+++ b/sys/external/bsd/drm2/include/linux/reservation.h Mon Aug 27 14:01:14 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: reservation.h,v 1.6 2018/08/27 13:55:46 riastradh Exp $ */
+/* $NetBSD: reservation.h,v 1.7 2018/08/27 14:01:14 riastradh Exp $ */
/*-
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -58,6 +58,7 @@
#define reservation_object_add_shared_fence linux_reservation_object_add_shared_fence
#define reservation_object_fini linux_reservation_object_fini
#define reservation_object_get_excl linux_reservation_object_get_excl
+#define reservation_object_get_fences_rcu linux_reservation_object_get_fences_rcu
#define reservation_object_get_list linux_reservation_object_get_list
#define reservation_object_held linux_reservation_object_held
#define reservation_object_init linux_reservation_object_init
@@ -80,6 +81,10 @@
struct fence *);
void reservation_object_add_shared_fence(struct reservation_object *,
struct fence *);
+
+int reservation_object_get_fences_rcu(struct reservation_object *,
+ struct fence **, unsigned *, struct fence ***);
+
bool reservation_object_test_signaled_rcu(struct reservation_object *,
bool);
long reservation_object_wait_timeout_rcu(struct reservation_object *,
diff -r cac9419cbb75 -r d3c1d640fde5 sys/external/bsd/drm2/linux/linux_reservation.c
--- a/sys/external/bsd/drm2/linux/linux_reservation.c Mon Aug 27 14:01:01 2018 +0000
+++ b/sys/external/bsd/drm2/linux/linux_reservation.c Mon Aug 27 14:01:14 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: linux_reservation.c,v 1.3 2018/08/27 13:55:46 riastradh Exp $ */
+/* $NetBSD: linux_reservation.c,v 1.4 2018/08/27 14:01:14 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.3 2018/08/27 13:55:46 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_reservation.c,v 1.4 2018/08/27 14:01:14 riastradh Exp $");
#include <linux/fence.h>
#include <linux/reservation.h>
@@ -444,6 +444,130 @@
fence_put(replace);
}
+int
+reservation_object_get_fences_rcu(struct reservation_object *robj,
+ struct fence **fencep, unsigned *nsharedp, struct fence ***sharedp)
+{
+ struct reservation_object_list *list;
+ struct fence *fence;
+ struct fence **shared = NULL;
+ unsigned shared_alloc, shared_count, i;
+ struct reservation_object_read_ticket ticket;
+
+top:
+ /* Enter an RCU read section and get a read ticket. */
+ rcu_read_lock();
+ reservation_object_read_begin(robj, &ticket);
+
+ /* If there is a shared list, grab it. */
+ if ((list = robj->robj_list) != NULL) {
+ /* Make sure the content of the list has been published. */
+ membar_datadep_consumer();
+
+ /* Check whether we have a buffer. */
+ if (shared == NULL) {
+ /*
+ * We don't have a buffer yet. Try to allocate
+ * one without waiting.
+ */
+ shared_alloc = list->shared_max;
+ __insn_barrier();
+ shared = kcalloc(shared_alloc, sizeof(shared[0]),
+ GFP_NOWAIT);
+ if (shared == NULL) {
+ /*
+ * Couldn't do it immediately. Back
+ * out of RCU and allocate one with
+ * waiting.
+ */
+ rcu_read_unlock();
+ shared = kcalloc(shared_alloc,
+ sizeof(shared[0]), GFP_KERNEL);
+ if (shared == NULL)
+ return -ENOMEM;
+ goto top;
+ }
+ } else if (shared_alloc < list->shared_max) {
+ /*
+ * We have a buffer but it's too small. We're
+ * already racing in this case, so just back
+ * out and wait to allocate a bigger one.
+ */
+ shared_alloc = list->shared_max;
+ __insn_barrier();
+ rcu_read_unlock();
+ kfree(shared);
+ shared = kcalloc(shared_alloc, sizeof(shared[0]),
+ GFP_KERNEL);
+ if (shared == NULL)
+ return -ENOMEM;
+ }
+
+ /*
+ * We got a buffer large enough. Copy into the buffer
+ * and record the number of elements.
+ */
+ memcpy(shared, list->shared, shared_alloc * sizeof(shared[0]));
+ shared_count = list->shared_count;
+ } else {
+ /* No shared list: shared count is zero. */
+ shared_count = 0;
+ }
+
+ /* If there is an exclusive fence, grab it. */
+ if ((fence = robj->robj_fence) != NULL) {
+ /* Make sure the content of the fence has been published. */
+ membar_datadep_consumer();
+ }
+
+ /*
+ * We are done reading from robj and list. Validate our
+ * parking ticket. If it's invalid, do not pass go and do not
+ * collect $200.
+ */
+ if (!reservation_object_read_valid(robj, &ticket))
+ goto restart;
+
+ /*
+ * Try to get a reference to the exclusive fence, if there is
+ * one. If we can't, start over.
+ */
+ if (fence) {
+ if (fence_get_rcu(fence) == NULL)
+ goto restart;
+ }
+
+ /*
+ * Try to get a reference to all of the shared fences.
+ */
+ for (i = 0; i < shared_count; i++) {
+ if (fence_get_rcu(shared[i]) == NULL)
+ goto put_restart;
+ }
+
+ /* Success! */
+ rcu_read_unlock();
+ *fencep = fence;
+ *nsharedp = shared_count;
+ *sharedp = shared;
+ return 0;
+
+put_restart:
+ /* Back out. */
+ while (i --> 0) {
+ fence_put(shared[i]);
+ shared[i] = NULL; /* paranoia */
+ }
+ if (fence) {
+ fence_put(fence);
+ fence = NULL; /* paranoia */
+ }
+
+restart:
+ rcu_read_unlock();
+ goto top;
+}
+
/*
* reservation_object_test_signaled_rcu(robj, shared)
*
Home |
Main Index |
Thread Index |
Old Index