diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2009-08-25 04:46:10 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2009-08-25 04:46:10 -0400 |
commit | 872fa3a2575486998d8b0380e5d6ef391d0305a8 (patch) | |
tree | 8a4c5b752a606589d66ba0fef6a6f2e9cd3dbbdf /kernel/rt.c | |
parent | dcd880ed997a25809731ef3e36488a1da3bf4edb (diff) |
rt: Fix recursive read lock of rw_semaphores
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/rt.c')
-rw-r--r-- | kernel/rt.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/kernel/rt.c b/kernel/rt.c index 7da32994e88f..710cef59ee8a 100644 --- a/kernel/rt.c +++ b/kernel/rt.c | |||
@@ -303,7 +303,8 @@ EXPORT_SYMBOL(rt_up_write); | |||
303 | void rt_up_read(struct rw_semaphore *rwsem) | 303 | void rt_up_read(struct rw_semaphore *rwsem) |
304 | { | 304 | { |
305 | rwsem_release(&rwsem->dep_map, 1, _RET_IP_); | 305 | rwsem_release(&rwsem->dep_map, 1, _RET_IP_); |
306 | rt_mutex_unlock(&rwsem->lock); | 306 | if (--rwsem->read_depth == 0) |
307 | rt_mutex_unlock(&rwsem->lock); | ||
307 | } | 308 | } |
308 | EXPORT_SYMBOL(rt_up_read); | 309 | EXPORT_SYMBOL(rt_up_read); |
309 | 310 | ||
@@ -314,6 +315,7 @@ EXPORT_SYMBOL(rt_up_read); | |||
314 | void rt_downgrade_write(struct rw_semaphore *rwsem) | 315 | void rt_downgrade_write(struct rw_semaphore *rwsem) |
315 | { | 316 | { |
316 | BUG_ON(rt_mutex_real_owner(&rwsem->lock) != current); | 317 | BUG_ON(rt_mutex_real_owner(&rwsem->lock) != current); |
318 | rwsem->read_depth = 1; | ||
317 | } | 319 | } |
318 | EXPORT_SYMBOL(rt_downgrade_write); | 320 | EXPORT_SYMBOL(rt_downgrade_write); |
319 | 321 | ||
@@ -343,18 +345,29 @@ EXPORT_SYMBOL(rt_down_write_nested); | |||
343 | 345 | ||
344 | int rt_down_read_trylock(struct rw_semaphore *rwsem) | 346 | int rt_down_read_trylock(struct rw_semaphore *rwsem) |
345 | { | 347 | { |
346 | int ret = rt_mutex_trylock(&rwsem->lock); | 348 | struct rt_mutex *lock = &rwsem->lock; |
349 | int ret = 1; | ||
347 | 350 | ||
348 | if (ret) | 351 | if (rt_mutex_real_owner(lock) != current) |
352 | ret = rt_mutex_trylock(&rwsem->lock); | ||
353 | |||
354 | if (ret) { | ||
355 | rwsem->read_depth++; | ||
349 | rwsem_acquire(&rwsem->dep_map, 0, 1, _RET_IP_); | 356 | rwsem_acquire(&rwsem->dep_map, 0, 1, _RET_IP_); |
357 | } | ||
350 | return ret; | 358 | return ret; |
351 | } | 359 | } |
352 | EXPORT_SYMBOL(rt_down_read_trylock); | 360 | EXPORT_SYMBOL(rt_down_read_trylock); |
353 | 361 | ||
354 | static void __rt_down_read(struct rw_semaphore *rwsem, int subclass) | 362 | static void __rt_down_read(struct rw_semaphore *rwsem, int subclass) |
355 | { | 363 | { |
364 | struct rt_mutex *lock = &rwsem->lock; | ||
365 | |||
356 | rwsem_acquire_read(&rwsem->dep_map, subclass, 0, _RET_IP_); | 366 | rwsem_acquire_read(&rwsem->dep_map, subclass, 0, _RET_IP_); |
357 | rt_mutex_lock(&rwsem->lock); | 367 | |
368 | if (rt_mutex_real_owner(lock) != current) | ||
369 | rt_mutex_lock(&rwsem->lock); | ||
370 | rwsem->read_depth++; | ||
358 | } | 371 | } |
359 | 372 | ||
360 | void rt_down_read(struct rw_semaphore *rwsem) | 373 | void rt_down_read(struct rw_semaphore *rwsem) |
@@ -380,6 +393,7 @@ void __rt_rwsem_init(struct rw_semaphore *rwsem, char *name, | |||
380 | lockdep_init_map(&rwsem->dep_map, name, key, 0); | 393 | lockdep_init_map(&rwsem->dep_map, name, key, 0); |
381 | #endif | 394 | #endif |
382 | __rt_mutex_init(&rwsem->lock, name); | 395 | __rt_mutex_init(&rwsem->lock, name); |
396 | rwsem->read_depth = 0; | ||
383 | } | 397 | } |
384 | EXPORT_SYMBOL(__rt_rwsem_init); | 398 | EXPORT_SYMBOL(__rt_rwsem_init); |
385 | 399 | ||