diff options
| author | Michel Lespinasse <walken@google.com> | 2013-05-07 09:45:52 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-07 10:20:16 -0400 |
| commit | da16922cc031b9c0221c836994276ab193b31de8 (patch) | |
| tree | 8765a482ab31db66f3cc9cab83bf67eaafe88f75 /lib | |
| parent | 1e78277ccbbb48af32a618d1ef0e8534e0b648d7 (diff) | |
rwsem: simplify rwsem_down_read_failed
When trying to acquire a read lock, the RWSEM_ACTIVE_READ_BIAS
adjustment doesn't cause other readers to block, so we never have to
worry about waking them back after canceling this adjustment in
rwsem_down_read_failed().
We also never want to steal the lock in rwsem_down_read_failed(), so we
don't have to grab the wait_lock either.
Signed-off-by: Michel Lespinasse <walken@google.com>
Reviewed-by: Rik van Riel <riel@redhat.com>
Reviewed-by: Peter Hurley <peter@hurleysoftware.com>
Acked-by: Davidlohr Bueso <davidlohr.bueso@hp.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/rwsem.c | 22 |
1 files changed, 2 insertions, 20 deletions
diff --git a/lib/rwsem.c b/lib/rwsem.c index fb658af1c12c..66f307e90761 100644 --- a/lib/rwsem.c +++ b/lib/rwsem.c | |||
| @@ -182,7 +182,6 @@ try_again_write: | |||
| 182 | */ | 182 | */ |
| 183 | struct rw_semaphore __sched *rwsem_down_read_failed(struct rw_semaphore *sem) | 183 | struct rw_semaphore __sched *rwsem_down_read_failed(struct rw_semaphore *sem) |
| 184 | { | 184 | { |
| 185 | enum rwsem_waiter_type type = RWSEM_WAITING_FOR_READ; | ||
| 186 | signed long adjustment = -RWSEM_ACTIVE_READ_BIAS; | 185 | signed long adjustment = -RWSEM_ACTIVE_READ_BIAS; |
| 187 | struct rwsem_waiter waiter; | 186 | struct rwsem_waiter waiter; |
| 188 | struct task_struct *tsk = current; | 187 | struct task_struct *tsk = current; |
| @@ -190,7 +189,7 @@ struct rw_semaphore __sched *rwsem_down_read_failed(struct rw_semaphore *sem) | |||
| 190 | 189 | ||
| 191 | /* set up my own style of waitqueue */ | 190 | /* set up my own style of waitqueue */ |
| 192 | waiter.task = tsk; | 191 | waiter.task = tsk; |
| 193 | waiter.type = type; | 192 | waiter.type = RWSEM_WAITING_FOR_READ; |
| 194 | get_task_struct(tsk); | 193 | get_task_struct(tsk); |
| 195 | 194 | ||
| 196 | raw_spin_lock_irq(&sem->wait_lock); | 195 | raw_spin_lock_irq(&sem->wait_lock); |
| @@ -201,17 +200,9 @@ struct rw_semaphore __sched *rwsem_down_read_failed(struct rw_semaphore *sem) | |||
| 201 | /* we're now waiting on the lock, but no longer actively locking */ | 200 | /* we're now waiting on the lock, but no longer actively locking */ |
| 202 | count = rwsem_atomic_update(adjustment, sem); | 201 | count = rwsem_atomic_update(adjustment, sem); |
| 203 | 202 | ||
| 204 | /* If there are no active locks, wake the front queued process(es) up. | 203 | /* If there are no active locks, wake the front queued process(es). */ |
| 205 | * | ||
| 206 | * Alternatively, if we're called from a failed down_write(), there | ||
| 207 | * were already threads queued before us and there are no active | ||
| 208 | * writers, the lock must be read owned; so we try to wake any read | ||
| 209 | * locks that were queued ahead of us. */ | ||
| 210 | if (count == RWSEM_WAITING_BIAS) | 204 | if (count == RWSEM_WAITING_BIAS) |
| 211 | sem = __rwsem_do_wake(sem, RWSEM_WAKE_NO_ACTIVE); | 205 | sem = __rwsem_do_wake(sem, RWSEM_WAKE_NO_ACTIVE); |
| 212 | else if (count > RWSEM_WAITING_BIAS && | ||
| 213 | adjustment == -RWSEM_ACTIVE_WRITE_BIAS) | ||
| 214 | sem = __rwsem_do_wake(sem, RWSEM_WAKE_READ_OWNED); | ||
| 215 | 206 | ||
| 216 | raw_spin_unlock_irq(&sem->wait_lock); | 207 | raw_spin_unlock_irq(&sem->wait_lock); |
| 217 | 208 | ||
| @@ -220,15 +211,6 @@ struct rw_semaphore __sched *rwsem_down_read_failed(struct rw_semaphore *sem) | |||
| 220 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); | 211 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); |
| 221 | if (!waiter.task) | 212 | if (!waiter.task) |
| 222 | break; | 213 | break; |
| 223 | |||
| 224 | raw_spin_lock_irq(&sem->wait_lock); | ||
| 225 | /* Try to get the writer sem, may steal from the head writer: */ | ||
| 226 | if (type == RWSEM_WAITING_FOR_WRITE) | ||
| 227 | if (try_get_writer_sem(sem, &waiter)) { | ||
| 228 | raw_spin_unlock_irq(&sem->wait_lock); | ||
| 229 | return sem; | ||
| 230 | } | ||
| 231 | raw_spin_unlock_irq(&sem->wait_lock); | ||
| 232 | schedule(); | 214 | schedule(); |
| 233 | } | 215 | } |
| 234 | 216 | ||
