History

locking/rwbase: Extract __rwbase_write_trylock()

The code in rwbase_write_lock() is a little non-obvious vs the read+set 'trylock', extract the sequence into a helper function to clarify the code. This also provides a single site to fix fast-path ordering.

Peter Zijlstra committed 5 years ago

Commit 616be871 parent 76872011 file · +26 −18Browse files

Showing the changes to kernel/locking (1 of 1 file). Show all

Unified · Split

kernel/locking/rwbase_rt.c+26−18
@@ -196,6 +196,19 @@ static inline void rwbase_write_downgrade(struct rwbase_rt *rwb) · 195 unmodified lines
196 __rwbase_write_unlock(rwb, WRITER_BIAS - 1, flags);196 __rwbase_write_unlock(rwb, WRITER_BIAS - 1, flags);
197}197}
198 198
199static inline bool __rwbase_write_trylock(struct rwbase_rt *rwb)
200{
201 /* Can do without CAS because we're serialized by wait_lock. */
202 lockdep_assert_held(&rwb->rtmutex.wait_lock);
203
204 if (!atomic_read(&rwb->readers)) {
205 atomic_set(&rwb->readers, WRITER_BIAS);
206 return 1;
207 }
208
209 return 0;
210}
211
199static int __sched rwbase_write_lock(struct rwbase_rt *rwb,212static int __sched rwbase_write_lock(struct rwbase_rt *rwb,
200 unsigned int state)213 unsigned int state)
201{214{
@@ -210,34 +223,30 @@ static int __sched rwbase_write_lock(struct rwbase_rt *rwb, · 8 unmodified lines
210 atomic_sub(READER_BIAS, &rwb->readers);223 atomic_sub(READER_BIAS, &rwb->readers);
211 224
212 raw_spin_lock_irqsave(&rtm->wait_lock, flags);225 raw_spin_lock_irqsave(&rtm->wait_lock, flags);
213 /*226 if (__rwbase_write_trylock(rwb))
214 * set_current_state() for rw_semaphore227 goto out_unlock;
215 * current_save_and_set_rtlock_wait_state() for rwlock
216 */
217 rwbase_set_and_save_current_state(state);
218 228
219 /* Block until all readers have left the critical section. */229 rwbase_set_and_save_current_state(state);
220 for (; atomic_read(&rwb->readers);) {230 for (;;) {
221 /* Optimized out for rwlocks */231 /* Optimized out for rwlocks */
222 if (rwbase_signal_pending_state(state, current)) {232 if (rwbase_signal_pending_state(state, current)) {
223 rwbase_restore_current_state();233 rwbase_restore_current_state();
224 __rwbase_write_unlock(rwb, 0, flags);234 __rwbase_write_unlock(rwb, 0, flags);
225 return -EINTR;235 return -EINTR;
226 }236 }
237
238 if (__rwbase_write_trylock(rwb))
239 break;
240
227 raw_spin_unlock_irqrestore(&rtm->wait_lock, flags);241 raw_spin_unlock_irqrestore(&rtm->wait_lock, flags);
242 rwbase_schedule();
243 raw_spin_lock_irqsave(&rtm->wait_lock, flags);
228 244
229 /*
230 * Schedule and wait for the readers to leave the critical
231 * section. The last reader leaving it wakes the waiter.
232 */
233 if (atomic_read(&rwb->readers) != 0)
234 rwbase_schedule();
235 set_current_state(state);245 set_current_state(state);
236 raw_spin_lock_irqsave(&rtm->wait_lock, flags);
237 }246 }
238
239 atomic_set(&rwb->readers, WRITER_BIAS);
240 rwbase_restore_current_state();247 rwbase_restore_current_state();
248
249out_unlock:
241 raw_spin_unlock_irqrestore(&rtm->wait_lock, flags);250 raw_spin_unlock_irqrestore(&rtm->wait_lock, flags);
242 return 0;251 return 0;
243}252}
@@ -253,8 +262,7 @@ static inline int rwbase_write_trylock(struct rwbase_rt *rwb) · 9 unmodified lines
253 atomic_sub(READER_BIAS, &rwb->readers);262 atomic_sub(READER_BIAS, &rwb->readers);
254 263
255 raw_spin_lock_irqsave(&rtm->wait_lock, flags);264 raw_spin_lock_irqsave(&rtm->wait_lock, flags);
256 if (!atomic_read(&rwb->readers)) {265 if (__rwbase_write_trylock(rwb)) {
257 atomic_set(&rwb->readers, WRITER_BIAS);
258 raw_spin_unlock_irqrestore(&rtm->wait_lock, flags);266 raw_spin_unlock_irqrestore(&rtm->wait_lock, flags);
259 return 1;267 return 1;
260 }268 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t