aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rt.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2009-08-25 04:46:10 -0400
committerThomas Gleixner <tglx@linutronix.de>2009-08-25 04:46:10 -0400
commit872fa3a2575486998d8b0380e5d6ef391d0305a8 (patch)
tree8a4c5b752a606589d66ba0fef6a6f2e9cd3dbbdf /kernel/rt.c
parentdcd880ed997a25809731ef3e36488a1da3bf4edb (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.c22
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);
303void rt_up_read(struct rw_semaphore *rwsem) 303void 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}
308EXPORT_SYMBOL(rt_up_read); 309EXPORT_SYMBOL(rt_up_read);
309 310
@@ -314,6 +315,7 @@ EXPORT_SYMBOL(rt_up_read);
314void rt_downgrade_write(struct rw_semaphore *rwsem) 315void 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}
318EXPORT_SYMBOL(rt_downgrade_write); 320EXPORT_SYMBOL(rt_downgrade_write);
319 321
@@ -343,18 +345,29 @@ EXPORT_SYMBOL(rt_down_write_nested);
343 345
344int rt_down_read_trylock(struct rw_semaphore *rwsem) 346int 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}
352EXPORT_SYMBOL(rt_down_read_trylock); 360EXPORT_SYMBOL(rt_down_read_trylock);
353 361
354static void __rt_down_read(struct rw_semaphore *rwsem, int subclass) 362static 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
360void rt_down_read(struct rw_semaphore *rwsem) 373void 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}
384EXPORT_SYMBOL(__rt_rwsem_init); 398EXPORT_SYMBOL(__rt_rwsem_init);
385 399