summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2009-09-14 19:01:21 +0200
committerThomas Gleixner <tglx@linutronix.de>2009-09-15 17:28:33 +0200
commit00261a9426ed50016e07cbef028578e93589761c (patch)
treead17506dd480e686ebd40610391099b7a143b457
parent0188eb5994a27527b0ed2770df56ca6565486713 (diff)
downloadlwn-00261a9426ed50016e07cbef028578e93589761c.tar.gz
lwn-00261a9426ed50016e07cbef028578e93589761c.zip
rt: Fix rwlocks/rwsem rt_[down_]read_trylock()
rt_read_trylock() and rt_down_read_trylock() take the lock / semaphore unconditionally when it is write locked. Check read_depth if current owns the lock. If it's 0 we know it is write locked and return 0. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--kernel/rt.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/kernel/rt.c b/kernel/rt.c
index 710cef59ee8a..fd033a9bd7c2 100644
--- a/kernel/rt.c
+++ b/kernel/rt.c
@@ -204,10 +204,14 @@ int __lockfunc rt_read_trylock(rwlock_t *rwlock)
int ret = 1;
/*
- * recursive read locks succeed when current owns the lock
+ * recursive read locks succeed when current owns the lock,
+ * but not when read_depth == 0 which means that the lock is
+ * write locked.
*/
if (rt_mutex_real_owner(lock) != current)
ret = rt_mutex_trylock(lock);
+ else if (!rwlock->read_depth)
+ ret = 0;
if (ret) {
rwlock->read_depth++;
@@ -348,8 +352,15 @@ int rt_down_read_trylock(struct rw_semaphore *rwsem)
struct rt_mutex *lock = &rwsem->lock;
int ret = 1;
+ /*
+ * recursive read locks succeed when current owns the rwsem,
+ * but not when read_depth == 0 which means that the rwsem is
+ * write locked.
+ */
if (rt_mutex_real_owner(lock) != current)
ret = rt_mutex_trylock(&rwsem->lock);
+ else if (!rwsem->read_depth)
+ ret = 0;
if (ret) {
rwsem->read_depth++;