diff options
author | Maarten Lankhorst <maarten.lankhorst@canonical.com> | 2014-07-01 06:58:00 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-07-08 16:41:08 -0400 |
commit | 3c3b177a9369b26890ced004867fb32708e8ef5b (patch) | |
tree | d7f1840cd62b8c0d427ea56b203485c2e27bb29e /include/linux/reservation.h | |
parent | 04a5faa8cbe5a8eaf152cb88959ba6360c26e702 (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.h | 52 |
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 | ||
46 | extern struct ww_class reservation_ww_class; | 48 | extern struct ww_class reservation_ww_class; |
49 | extern struct lock_class_key reservation_seqcount_class; | ||
50 | extern const char reservation_seqcount_string[]; | ||
47 | 51 | ||
48 | struct reservation_object_list { | 52 | struct 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 | ||
53 | struct reservation_object { | 58 | struct 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) | |||
99 | static inline struct reservation_object_list * | 109 | static inline struct reservation_object_list * |
100 | reservation_object_get_list(struct reservation_object *obj) | 110 | reservation_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 | ||
107 | static inline struct fence * | 116 | static inline struct fence * |
108 | reservation_object_get_excl(struct reservation_object *obj) | 117 | reservation_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 | ||
115 | int reservation_object_reserve_shared(struct reservation_object *obj); | 123 | int reservation_object_reserve_shared(struct reservation_object *obj); |
@@ -119,4 +127,16 @@ void reservation_object_add_shared_fence(struct reservation_object *obj, | |||
119 | void reservation_object_add_excl_fence(struct reservation_object *obj, | 127 | void reservation_object_add_excl_fence(struct reservation_object *obj, |
120 | struct fence *fence); | 128 | struct fence *fence); |
121 | 129 | ||
130 | int reservation_object_get_fences_rcu(struct reservation_object *obj, | ||
131 | struct fence **pfence_excl, | ||
132 | unsigned *pshared_count, | ||
133 | struct fence ***pshared); | ||
134 | |||
135 | long reservation_object_wait_timeout_rcu(struct reservation_object *obj, | ||
136 | bool wait_all, bool intr, | ||
137 | unsigned long timeout); | ||
138 | |||
139 | bool reservation_object_test_signaled_rcu(struct reservation_object *obj, | ||
140 | bool test_all); | ||
141 | |||
122 | #endif /* _LINUX_RESERVATION_H */ | 142 | #endif /* _LINUX_RESERVATION_H */ |