@@ -74,12 +74,21 @@ impl MutexMetadata {
74
74
}
75
75
}
76
76
77
- fn pre_lock ( this : & Arc < MutexMetadata > ) {
77
+ fn pre_lock ( this : & Arc < MutexMetadata > , read : bool ) {
78
78
MUTEXES_HELD . with ( |held| {
79
79
// For each mutex which is currently locked, check that no mutex's locked-before
80
80
// set includes the mutex we're about to lock, which would imply a lockorder
81
81
// inversion.
82
82
for locked in held. borrow ( ) . iter ( ) {
83
+ if read && * locked == * this {
84
+ // Recursive read locks are explicitly allowed
85
+ return ;
86
+ }
87
+ }
88
+ for locked in held. borrow ( ) . iter ( ) {
89
+ if !read && * locked == * this {
90
+ panic ! ( "Tried to lock a mutex while it was held!" ) ;
91
+ }
83
92
for locked_dep in locked. locked_before . lock ( ) . unwrap ( ) . iter ( ) {
84
93
if * locked_dep == * this {
85
94
#[ cfg( feature = "backtrace" ) ]
@@ -158,7 +167,7 @@ impl<T> Mutex<T> {
158
167
}
159
168
160
169
pub fn lock < ' a > ( & ' a self ) -> LockResult < MutexGuard < ' a , T > > {
161
- MutexMetadata :: pre_lock ( & self . deps ) ;
170
+ MutexMetadata :: pre_lock ( & self . deps , false ) ;
162
171
self . inner . lock ( ) . map ( |lock| MutexGuard { mutex : self , lock } ) . map_err ( |_| ( ) )
163
172
}
164
173
@@ -171,54 +180,109 @@ impl<T> Mutex<T> {
171
180
}
172
181
}
173
182
174
- pub struct RwLock < T : ?Sized > {
175
- inner : StdRwLock < T >
183
+ pub struct RwLock < T : Sized > {
184
+ inner : StdRwLock < T > ,
185
+ deps : Arc < MutexMetadata > ,
176
186
}
177
187
178
- pub struct RwLockReadGuard < ' a , T : ?Sized + ' a > {
188
+ pub struct RwLockReadGuard < ' a , T : Sized + ' a > {
189
+ mutex : & ' a RwLock < T > ,
179
190
lock : StdRwLockReadGuard < ' a , T > ,
180
191
}
181
192
182
- pub struct RwLockWriteGuard < ' a , T : ?Sized + ' a > {
193
+ pub struct RwLockWriteGuard < ' a , T : Sized + ' a > {
194
+ mutex : & ' a RwLock < T > ,
183
195
lock : StdRwLockWriteGuard < ' a , T > ,
184
196
}
185
197
186
- impl < T : ? Sized > Deref for RwLockReadGuard < ' _ , T > {
198
+ impl < T : Sized > Deref for RwLockReadGuard < ' _ , T > {
187
199
type Target = T ;
188
200
189
201
fn deref ( & self ) -> & T {
190
202
& self . lock . deref ( )
191
203
}
192
204
}
193
205
194
- impl < T : ?Sized > Deref for RwLockWriteGuard < ' _ , T > {
206
+ impl < T : Sized > Drop for RwLockReadGuard < ' _ , T > {
207
+ fn drop ( & mut self ) {
208
+ MUTEXES_HELD . with ( |held| {
209
+ held. borrow_mut ( ) . remove ( & self . mutex . deps ) ;
210
+ } ) ;
211
+ }
212
+ }
213
+
214
+ impl < T : Sized > Deref for RwLockWriteGuard < ' _ , T > {
195
215
type Target = T ;
196
216
197
217
fn deref ( & self ) -> & T {
198
218
& self . lock . deref ( )
199
219
}
200
220
}
201
221
202
- impl < T : ?Sized > DerefMut for RwLockWriteGuard < ' _ , T > {
222
+ impl < T : Sized > Drop for RwLockWriteGuard < ' _ , T > {
223
+ fn drop ( & mut self ) {
224
+ MUTEXES_HELD . with ( |held| {
225
+ held. borrow_mut ( ) . remove ( & self . mutex . deps ) ;
226
+ } ) ;
227
+ }
228
+ }
229
+
230
+ impl < T : Sized > DerefMut for RwLockWriteGuard < ' _ , T > {
203
231
fn deref_mut ( & mut self ) -> & mut T {
204
232
self . lock . deref_mut ( )
205
233
}
206
234
}
207
235
208
236
impl < T > RwLock < T > {
209
237
pub fn new ( inner : T ) -> RwLock < T > {
210
- RwLock { inner : StdRwLock :: new ( inner) }
238
+ RwLock { inner : StdRwLock :: new ( inner) , deps : Arc :: new ( MutexMetadata :: new ( ) ) }
211
239
}
212
240
213
241
pub fn read < ' a > ( & ' a self ) -> LockResult < RwLockReadGuard < ' a , T > > {
214
- self . inner . read ( ) . map ( |lock| RwLockReadGuard { lock } ) . map_err ( |_| ( ) )
242
+ MutexMetadata :: pre_lock ( & self . deps , true ) ;
243
+ self . inner . read ( ) . map ( |lock| RwLockReadGuard { mutex : self , lock } ) . map_err ( |_| ( ) )
215
244
}
216
245
217
246
pub fn write < ' a > ( & ' a self ) -> LockResult < RwLockWriteGuard < ' a , T > > {
218
- self . inner . write ( ) . map ( |lock| RwLockWriteGuard { lock } ) . map_err ( |_| ( ) )
247
+ MutexMetadata :: pre_lock ( & self . deps , false ) ;
248
+ self . inner . write ( ) . map ( |lock| RwLockWriteGuard { mutex : self , lock } ) . map_err ( |_| ( ) )
219
249
}
220
250
221
251
pub fn try_write < ' a > ( & ' a self ) -> LockResult < RwLockWriteGuard < ' a , T > > {
222
- self . inner . try_write ( ) . map ( |lock| RwLockWriteGuard { lock } ) . map_err ( |_| ( ) )
252
+ let res = self . inner . try_write ( ) . map ( |lock| RwLockWriteGuard { mutex : self , lock } ) . map_err ( |_| ( ) ) ;
253
+ if res. is_ok ( ) {
254
+ MutexMetadata :: try_locked ( & self . deps ) ;
255
+ }
256
+ res
257
+ }
258
+ }
259
+
260
+ #[ test]
261
+ #[ should_panic]
262
+ fn recursive_lock_fail ( ) {
263
+ let mutex = Mutex :: new ( ( ) ) ;
264
+ let _a = mutex. lock ( ) . unwrap ( ) ;
265
+ let _b = mutex. lock ( ) . unwrap ( ) ;
266
+ }
267
+
268
+ #[ test]
269
+ fn recursive_read ( ) {
270
+ let mutex = RwLock :: new ( ( ) ) ;
271
+ let _a = mutex. read ( ) . unwrap ( ) ;
272
+ let _b = mutex. read ( ) . unwrap ( ) ;
273
+ }
274
+
275
+ #[ test]
276
+ #[ should_panic]
277
+ fn lockorder_fail ( ) {
278
+ let a = Mutex :: new ( ( ) ) ;
279
+ let b = Mutex :: new ( ( ) ) ;
280
+ {
281
+ let _a = a. lock ( ) . unwrap ( ) ;
282
+ let _b = b. lock ( ) . unwrap ( ) ;
283
+ }
284
+ {
285
+ let _b = b. lock ( ) . unwrap ( ) ;
286
+ let _a = a. lock ( ) . unwrap ( ) ;
223
287
}
224
288
}
0 commit comments