Skip to content

Commit 6a97734

Browse files
ubizjakIngo Molnar
authored andcommitted
locking/pvqspinlock: Use try_cmpxchg_acquire() in trylock_clear_pending()
Replace this pattern in trylock_clear_pending(): cmpxchg_acquire(*ptr, old, new) == old ... with the simpler and faster: try_cmpxchg_acquire(*ptr, &old, new) The x86 CMPXCHG instruction returns success in the ZF flag, so this change saves a compare after the CMPXCHG. Also change the return type of the function to bool and streamline the control flow in the _Q_PENDING_BITS == 8 variant a bit. No functional change intended. Signed-off-by: Uros Bizjak <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Reviewed-by: Waiman Long <[email protected]> Reviewed-by: Linus Torvalds <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 79a34e3 commit 6a97734

File tree

1 file changed

+13
-18
lines changed

1 file changed

+13
-18
lines changed

kernel/locking/qspinlock_paravirt.h

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -116,39 +116,34 @@ static __always_inline void set_pending(struct qspinlock *lock)
116116
* barrier. Therefore, an atomic cmpxchg_acquire() is used to acquire the
117117
* lock just to be sure that it will get it.
118118
*/
119-
static __always_inline int trylock_clear_pending(struct qspinlock *lock)
119+
static __always_inline bool trylock_clear_pending(struct qspinlock *lock)
120120
{
121+
u16 old = _Q_PENDING_VAL;
122+
121123
return !READ_ONCE(lock->locked) &&
122-
(cmpxchg_acquire(&lock->locked_pending, _Q_PENDING_VAL,
123-
_Q_LOCKED_VAL) == _Q_PENDING_VAL);
124+
try_cmpxchg_acquire(&lock->locked_pending, &old, _Q_LOCKED_VAL);
124125
}
125126
#else /* _Q_PENDING_BITS == 8 */
126127
static __always_inline void set_pending(struct qspinlock *lock)
127128
{
128129
atomic_or(_Q_PENDING_VAL, &lock->val);
129130
}
130131

131-
static __always_inline int trylock_clear_pending(struct qspinlock *lock)
132+
static __always_inline bool trylock_clear_pending(struct qspinlock *lock)
132133
{
133-
int val = atomic_read(&lock->val);
134-
135-
for (;;) {
136-
int old, new;
137-
138-
if (val & _Q_LOCKED_MASK)
139-
break;
134+
int old, new;
140135

136+
old = atomic_read(&lock->val);
137+
do {
138+
if (old & _Q_LOCKED_MASK)
139+
return false;
141140
/*
142141
* Try to clear pending bit & set locked bit
143142
*/
144-
old = val;
145-
new = (val & ~_Q_PENDING_MASK) | _Q_LOCKED_VAL;
146-
val = atomic_cmpxchg_acquire(&lock->val, old, new);
143+
new = (old & ~_Q_PENDING_MASK) | _Q_LOCKED_VAL;
144+
} while (!atomic_try_cmpxchg_acquire (&lock->val, &old, new));
147145

148-
if (val == old)
149-
return 1;
150-
}
151-
return 0;
146+
return true;
152147
}
153148
#endif /* _Q_PENDING_BITS == 8 */
154149

0 commit comments

Comments
 (0)