aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/reservation.h
diff options
context:
space:
mode:
authorMaarten Lankhorst <maarten.lankhorst@canonical.com>2014-07-01 06:58:00 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-07-08 16:41:08 -0400
commit3c3b177a9369b26890ced004867fb32708e8ef5b (patch)
treed7f1840cd62b8c0d427ea56b203485c2e27bb29e /include/linux/reservation.h
parent04a5faa8cbe5a8eaf152cb88959ba6360c26e702 (diff)
reservation: add suppport for read-only access using rcu
This adds some extra functions to deal with rcu. reservation_object_get_fences_rcu() will obtain the list of shared and exclusive fences without obtaining the ww_mutex. reservation_object_wait_timeout_rcu() will wait on all fences of the reservation_object, without obtaining the ww_mutex. reservation_object_test_signaled_rcu() will test if all fences of the reservation_object are signaled without using the ww_mutex. reservation_object_get_excl and reservation_object_get_list require the reservation object to be held, updating requires write_seqcount_begin/end. If only the exclusive fence is needed, rcu_dereference followed by fence_get_rcu can be used, if the shared fences are needed it's recommended to use the supplied functions. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@canonical.com> Acked-by: Sumit Semwal <sumit.semwal@linaro.org> Acked-by: Daniel Vetter <daniel@ffwll.ch> Reviewed-By: Thomas Hellstrom <thellstrom@vmware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'include/linux/reservation.h')
-rw-r--r--include/linux/reservation.h52
1 files changed, 36 insertions, 16 deletions
diff --git a/include/linux/reservation.h b/include/linux/reservation.h
index 2affe67dea6e..5a0b64cf68b4 100644
--- a/include/linux/reservation.h
+++ b/include/linux/reservation.h
@@ -42,22 +42,29 @@
42#include <linux/ww_mutex.h> 42#include <linux/ww_mutex.h>
43#include <linux/fence.h> 43#include <linux/fence.h>
44#include <linux/slab.h> 44#include <linux/slab.h>
45#include <linux/seqlock.h>
46#include <linux/rcupdate.h>
45 47
46extern struct ww_class reservation_ww_class; 48extern struct ww_class reservation_ww_class;
49extern struct lock_class_key reservation_seqcount_class;
50extern const char reservation_seqcount_string[];
47 51
48struct reservation_object_list { 52struct reservation_object_list {
53 struct rcu_head rcu;
49 u32 shared_count, shared_max; 54 u32 shared_count, shared_max;
50 struct fence *shared[]; 55 struct fence __rcu *shared[];
51}; 56};
52 57
53struct reservation_object { 58struct reservation_object {
54 struct ww_mutex lock; 59 struct ww_mutex lock;
60 seqcount_t seq;
55 61
56 struct fence *fence_excl; 62 struct fence __rcu *fence_excl;
57 struct reservation_object_list *fence; 63 struct reservation_object_list __rcu *fence;
58 struct reservation_object_list *staged; 64 struct reservation_object_list *staged;
59}; 65};
60 66
67#define reservation_object_held(obj) lockdep_is_held(&(obj)->lock.base)
61#define reservation_object_assert_held(obj) \ 68#define reservation_object_assert_held(obj) \
62 lockdep_assert_held(&(obj)->lock.base) 69 lockdep_assert_held(&(obj)->lock.base)
63 70
@@ -66,8 +73,9 @@ reservation_object_init(struct reservation_object *obj)
66{ 73{
67 ww_mutex_init(&obj->lock, &reservation_ww_class); 74 ww_mutex_init(&obj->lock, &reservation_ww_class);
68 75
69 obj->fence_excl = NULL; 76 __seqcount_init(&obj->seq, reservation_seqcount_string, &reservation_seqcount_class);
70 obj->fence = NULL; 77 RCU_INIT_POINTER(obj->fence, NULL);
78 RCU_INIT_POINTER(obj->fence_excl, NULL);
71 obj->staged = NULL; 79 obj->staged = NULL;
72} 80}
73 81
@@ -76,18 +84,20 @@ reservation_object_fini(struct reservation_object *obj)
76{ 84{
77 int i; 85 int i;
78 struct reservation_object_list *fobj; 86 struct reservation_object_list *fobj;
87 struct fence *excl;
79 88
80 /* 89 /*
81 * This object should be dead and all references must have 90 * This object should be dead and all references must have
82 * been released to it. 91 * been released to it, so no need to be protected with rcu.
83 */ 92 */
84 if (obj->fence_excl) 93 excl = rcu_dereference_protected(obj->fence_excl, 1);
85 fence_put(obj->fence_excl); 94 if (excl)
95 fence_put(excl);
86 96
87 fobj = obj->fence; 97 fobj = rcu_dereference_protected(obj->fence, 1);
88 if (fobj) { 98 if (fobj) {
89 for (i = 0; i < fobj->shared_count; ++i) 99 for (i = 0; i < fobj->shared_count; ++i)
90 fence_put(fobj->shared[i]); 100 fence_put(rcu_dereference_protected(fobj->shared[i], 1));
91 101
92 kfree(fobj); 102 kfree(fobj);
93 } 103 }
@@ -99,17 +109,15 @@ reservation_object_fini(struct reservation_object *obj)
99static inline struct reservation_object_list * 109static inline struct reservation_object_list *
100reservation_object_get_list(struct reservation_object *obj) 110reservation_object_get_list(struct reservation_object *obj)
101{ 111{
102 reservation_object_assert_held(obj); 112 return rcu_dereference_protected(obj->fence,
103 113 reservation_object_held(obj));
104 return obj->fence;
105} 114}
106 115
107static inline struct fence * 116static inline struct fence *
108reservation_object_get_excl(struct reservation_object *obj) 117reservation_object_get_excl(struct reservation_object *obj)
109{ 118{
110 reservation_object_assert_held(obj); 119 return rcu_dereference_protected(obj->fence_excl,
111 120 reservation_object_held(obj));
112 return obj->fence_excl;
113} 121}
114 122
115int reservation_object_reserve_shared(struct reservation_object *obj); 123int reservation_object_reserve_shared(struct reservation_object *obj);
@@ -119,4 +127,16 @@ void reservation_object_add_shared_fence(struct reservation_object *obj,
119void reservation_object_add_excl_fence(struct reservation_object *obj, 127void reservation_object_add_excl_fence(struct reservation_object *obj,
120 struct fence *fence); 128 struct fence *fence);
121 129
130int reservation_object_get_fences_rcu(struct reservation_object *obj,
131 struct fence **pfence_excl,
132 unsigned *pshared_count,
133 struct fence ***pshared);
134
135long reservation_object_wait_timeout_rcu(struct reservation_object *obj,
136 bool wait_all, bool intr,
137 unsigned long timeout);
138
139bool reservation_object_test_signaled_rcu(struct reservation_object *obj,
140 bool test_all);
141
122#endif /* _LINUX_RESERVATION_H */ 142#endif /* _LINUX_RESERVATION_H */