diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2009-09-14 19:01:21 +0200 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2009-09-15 17:28:33 +0200 |
commit | 00261a9426ed50016e07cbef028578e93589761c (patch) | |
tree | ad17506dd480e686ebd40610391099b7a143b457 | |
parent | 0188eb5994a27527b0ed2770df56ca6565486713 (diff) | |
download | lwn-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.c | 13 |
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++; |