Read lock recursion is no longer required for ldisc references; remove mechanism. Signed-off-by: Peter Hurley <peter@xxxxxxxxxxxxxxxxxx> --- drivers/tty/tty_ldsem.c | 83 +++++------------------------------------------ include/linux/tty_ldisc.h | 2 -- 2 files changed, 8 insertions(+), 77 deletions(-) diff --git a/drivers/tty/tty_ldsem.c b/drivers/tty/tty_ldsem.c index c162295..a60d7e3 100644 --- a/drivers/tty/tty_ldsem.c +++ b/drivers/tty/tty_ldsem.c @@ -3,28 +3,14 @@ * * The ldisc semaphore is semantically a rw_semaphore but which enforces * an alternate policy, namely: - * 1) Recursive read locking is allowed - * 2) Supports lock wait timeouts - * 3) Write waiter has priority, even if lock is already read owned, except: - * 4) Write waiter does not prevent recursive locking - * 5) Downgrading is not supported (because of #3 & #4 above) + * 1) Supports lock wait timeouts + * 2) Write waiter has priority + * 3) Downgrading is not supported * * Implementation notes: * 1) Upper half of semaphore count is a wait count (differs from rwsem * in that rwsem normalizes the upper half to the wait bias) * 2) Lacks overflow checking - * 3) Read recursion is tracked with a bitmap indexed by hashed 'current' - * This approach results in some false positives; ie, a non-recursive - * read lock may be granted while a write lock is waited. - * However, this approach does not produce false-negatives - * (ie. not granting a read lock to a recursive attempt) which might - * deadlock. - * Testing the bitmap need not be atomic wrt. setting the bitmap - * (as the 'current' thread cannot contend with itself); however, - * since the bitmap is cleared when write lock is granted. - * Note: increasing the bitmap size reduces the probability of false - * positives, and thus the probability of granting a non-recursive - * read lock with writer(s) waiting. * * The generic counting was copied and modified from include/asm-generic/rwsem.h * by Paul Mackerras <paulus@xxxxxxxxx>. @@ -53,12 +39,12 @@ # ifdef CONFIG_PROVE_LOCKING # define lockdep_acquire(l, s, t, i) __acq(l, s, t, 0, 2, NULL, i) # define lockdep_acquire_nest(l, s, t, n, i) __acq(l, s, t, 0, 2, n, i) -# define lockdep_acquire_read(l, s, t, i) __acq(l, s, t, 2, 2, NULL, i) +# define lockdep_acquire_read(l, s, t, i) __acq(l, s, t, 1, 2, NULL, i) # define lockdep_release(l, n, i) __rel(l, n, i) # else # define lockdep_acquire(l, s, t, i) __acq(l, s, t, 0, 1, NULL, i) # define lockdep_acquire_nest(l, s, t, n, i) __acq(l, s, t, 0, 1, n, i) -# define lockdep_acquire_read(l, s, t, i) __acq(l, s, t, 2, 1, NULL, i) +# define lockdep_acquire_read(l, s, t, i) __acq(l, s, t, 1, 1, NULL, i) # define lockdep_release(l, n, i) __rel(l, n, i) # endif #else @@ -107,26 +93,6 @@ static inline long ldsem_atomic_update(long delta, struct ld_semaphore *sem) } -static inline unsigned long __hash_current(void) -{ - return (unsigned long)current % TASK_MAP_BITS; -} - -static inline void ldsem_clear_task_map(struct ld_semaphore *sem) -{ - bitmap_zero(sem->task_map, TASK_MAP_BITS); -} - -static inline void ldsem_update_task_map(struct ld_semaphore *sem) -{ - __set_bit(__hash_current(), sem->task_map); -} - -static inline int ldsem_lock_recursion(struct ld_semaphore *sem) -{ - return test_bit(__hash_current(), sem->task_map); -} - /* * Initialize an ldsem: */ @@ -144,7 +110,6 @@ void __init_ldsem(struct ld_semaphore *sem, const char *name, raw_spin_lock_init(&sem->wait_lock); INIT_LIST_HEAD(&sem->read_wait); INIT_LIST_HEAD(&sem->write_wait); - ldsem_clear_task_map(sem); } static void __ldsem_wake_readers(struct ld_semaphore *sem, int wake_type) @@ -217,9 +182,6 @@ static void __ldsem_wake_writer(struct ld_semaphore *sem) return; } while (1); - /* reset read lock recursion map */ - ldsem_clear_task_map(sem); - /* We must be careful not to touch 'waiter' after we set ->task = NULL. * It is an allocated on the waiter's stack and may become invalid at * any time after that point (due to a wakeup from another source). @@ -268,17 +230,9 @@ down_failed(struct ld_semaphore *sem, unsigned flags, long adjust, long timeout) /* set up my own style of waitqueue */ raw_spin_lock_irq(&sem->wait_lock); - if (flags & LDSEM_READ_WAIT) { - /* Handle recursive read locking -- if the reader already has - * a read lock then allow lock acquire without waiting - * but also without waking other waiters - */ - if (ldsem_lock_recursion(sem)) { - raw_spin_unlock_irq(&sem->wait_lock); - return sem; - } + if (flags & LDSEM_READ_WAIT) list_add_tail(&waiter.list, &sem->read_wait); - } else + else list_add_tail(&waiter.list, &sem->write_wait); waiter.task = current; @@ -358,9 +312,6 @@ static inline int __ldsem_down_read_nested(struct ld_semaphore *sem, } } lock_stat(sem, acquired); - - /* used for read lock recursion test */ - ldsem_update_task_map(sem); return 1; } @@ -371,17 +322,9 @@ static inline int __ldsem_down_write_nested(struct ld_semaphore *sem, lockdep_acquire(sem, subclass, 0, _RET_IP_); - raw_spin_lock_irq(&sem->wait_lock); - count = atomic_long_add_return(LDSEM_WRITE_BIAS, (atomic_long_t *)&sem->count); - if (count == LDSEM_WRITE_BIAS) { - /* reset read lock recursion map */ - ldsem_clear_task_map(sem); - raw_spin_unlock_irq(&sem->wait_lock); - } else { - raw_spin_unlock_irq(&sem->wait_lock); - + if (count != LDSEM_WRITE_BIAS) { lock_stat(sem, contended); if (!down_write_failed(sem, timeout)) { lockdep_release(sem, 1, _RET_IP_); @@ -414,8 +357,6 @@ int ldsem_down_read_trylock(struct ld_semaphore *sem) count + LDSEM_READ_BIAS)) { lockdep_acquire_read(sem, 0, 1, _RET_IP_); lock_stat(sem, acquired); - - ldsem_update_task_map(sem); return 1; } } @@ -438,21 +379,13 @@ int ldsem_down_write_trylock(struct ld_semaphore *sem) { long count; - raw_spin_lock_irq(&sem->wait_lock); - count = atomic_long_cmpxchg(&sem->count, LDSEM_UNLOCKED, LDSEM_WRITE_BIAS); if (count == LDSEM_UNLOCKED) { - /* reset read lock recursion map */ - ldsem_clear_task_map(sem); - - raw_spin_unlock_irq(&sem->wait_lock); - lockdep_acquire(sem, 0, 1, _RET_IP_); lock_stat(sem, acquired); return 1; } - raw_spin_unlock_irq(&sem->wait_lock); return 0; } diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index bbefe71..bfbe41a 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h @@ -122,8 +122,6 @@ struct ld_semaphore { #ifdef CONFIG_DEBUG_LOCK_ALLOC struct lockdep_map dep_map; #endif -#define TASK_MAP_BITS 157 - DECLARE_BITMAP(task_map, TASK_MAP_BITS); }; extern void __init_ldsem(struct ld_semaphore *sem, const char *name, -- 1.8.1.2 -- To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html