diff options
| author | Michel Lespinasse <walken@google.com> | 2013-05-07 09:45:55 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-07 10:20:16 -0400 |
| commit | 5ede972df1cd9294c82e9515949fd2103be81d7b (patch) | |
| tree | 2c6df4c16fbe4430ea2723f2aec284105aab08db /lib | |
| parent | ed00f64346631dff035adfb9b0240daaa8b46c4e (diff) | |
rwsem: use cmpxchg for trying to steal write lock
Using rwsem_atomic_update to try stealing the write lock forced us to
undo the adjustment in the failure path. We can have simpler and faster
code by using cmpxchg instead.
Signed-off-by: Michel Lespinasse <walken@google.com>
Reviewed-by: Peter Hurley <peter@hurleysoftware.com>
Acked-by: Davidlohr Bueso <davidlohr.bueso@hp.com>
Acked-by: Rik van Riel <riel@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/rwsem.c | 26 |
1 files changed, 6 insertions, 20 deletions
diff --git a/lib/rwsem.c b/lib/rwsem.c index 2360bf204098..64c2dc007be2 100644 --- a/lib/rwsem.c +++ b/lib/rwsem.c | |||
| @@ -142,25 +142,6 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wake_type) | |||
| 142 | return sem; | 142 | return sem; |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | /* Try to get write sem, caller holds sem->wait_lock: */ | ||
| 146 | static int try_get_writer_sem(struct rw_semaphore *sem) | ||
| 147 | { | ||
| 148 | long oldcount, adjustment; | ||
| 149 | |||
| 150 | adjustment = RWSEM_ACTIVE_WRITE_BIAS; | ||
| 151 | if (list_is_singular(&sem->wait_list)) | ||
| 152 | adjustment -= RWSEM_WAITING_BIAS; | ||
| 153 | |||
| 154 | try_again_write: | ||
| 155 | oldcount = rwsem_atomic_update(adjustment, sem) - adjustment; | ||
| 156 | if (!(oldcount & RWSEM_ACTIVE_MASK)) | ||
| 157 | return 1; | ||
| 158 | /* some one grabbed the sem already */ | ||
| 159 | if (rwsem_atomic_update(-adjustment, sem) & RWSEM_ACTIVE_MASK) | ||
| 160 | return 0; | ||
| 161 | goto try_again_write; | ||
| 162 | } | ||
| 163 | |||
| 164 | /* | 145 | /* |
| 165 | * wait for the read lock to be granted | 146 | * wait for the read lock to be granted |
| 166 | */ | 147 | */ |
| @@ -236,7 +217,12 @@ struct rw_semaphore __sched *rwsem_down_write_failed(struct rw_semaphore *sem) | |||
| 236 | while (true) { | 217 | while (true) { |
| 237 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); | 218 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); |
| 238 | 219 | ||
| 239 | if (try_get_writer_sem(sem)) | 220 | /* Try acquiring the write lock. */ |
| 221 | count = RWSEM_ACTIVE_WRITE_BIAS; | ||
| 222 | if (!list_is_singular(&sem->wait_list)) | ||
| 223 | count += RWSEM_WAITING_BIAS; | ||
| 224 | if (cmpxchg(&sem->count, RWSEM_WAITING_BIAS, count) == | ||
| 225 | RWSEM_WAITING_BIAS) | ||
| 240 | break; | 226 | break; |
| 241 | 227 | ||
| 242 | raw_spin_unlock_irq(&sem->wait_lock); | 228 | raw_spin_unlock_irq(&sem->wait_lock); |
