Skip to content

Commit f656864

Browse files
npigginmpe
authored andcommitted
powerpc/qspinlock: stop queued waiters trying to set lock sleepy
If a queued waiter notices the lock owner or the previous waiter has been preempted, it attempts to mark the lock sleepy, but it does this as a try-set operation using the original lock value it got when queueing, which will become stale as the queue progresses, and the try-set will fail. Drop this and just set the sleepy seen clock. Signed-off-by: Nicholas Piggin <[email protected]> Tested-by: Shrikanth Hegde <[email protected]> Reviewed-by: "Nysal Jan K.A" <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://msgid.link/[email protected]
1 parent ea142e5 commit f656864

File tree

1 file changed

+10
-14
lines changed

1 file changed

+10
-14
lines changed

arch/powerpc/lib/qspinlock.c

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -247,22 +247,18 @@ static __always_inline void seen_sleepy_lock(void)
247247
this_cpu_write(sleepy_lock_seen_clock, sched_clock());
248248
}
249249

250-
static __always_inline void seen_sleepy_node(struct qspinlock *lock, u32 val)
250+
static __always_inline void seen_sleepy_node(void)
251251
{
252252
if (pv_sleepy_lock) {
253253
if (pv_sleepy_lock_interval_ns)
254254
this_cpu_write(sleepy_lock_seen_clock, sched_clock());
255-
if (val & _Q_LOCKED_VAL) {
256-
if (!(val & _Q_SLEEPY_VAL))
257-
try_set_sleepy(lock, val);
258-
}
255+
/* Don't set sleepy because we likely have a stale val */
259256
}
260257
}
261258

262-
static struct qnode *get_tail_qnode(struct qspinlock *lock, u32 val)
259+
static struct qnode *get_tail_qnode(struct qspinlock *lock, int prev_cpu)
263260
{
264-
int cpu = decode_tail_cpu(val);
265-
struct qnodes *qnodesp = per_cpu_ptr(&qnodes, cpu);
261+
struct qnodes *qnodesp = per_cpu_ptr(&qnodes, prev_cpu);
266262
int idx;
267263

268264
/*
@@ -381,9 +377,8 @@ static __always_inline void propagate_yield_cpu(struct qnode *node, u32 val, int
381377
}
382378

383379
/* Called inside spin_begin() */
384-
static __always_inline bool yield_to_prev(struct qspinlock *lock, struct qnode *node, u32 val, bool paravirt)
380+
static __always_inline bool yield_to_prev(struct qspinlock *lock, struct qnode *node, int prev_cpu, bool paravirt)
385381
{
386-
int prev_cpu = decode_tail_cpu(val);
387382
u32 yield_count;
388383
int yield_cpu;
389384
bool preempted = false;
@@ -412,7 +407,7 @@ static __always_inline bool yield_to_prev(struct qspinlock *lock, struct qnode *
412407
spin_end();
413408

414409
preempted = true;
415-
seen_sleepy_node(lock, val);
410+
seen_sleepy_node();
416411

417412
smp_rmb();
418413

@@ -436,7 +431,7 @@ static __always_inline bool yield_to_prev(struct qspinlock *lock, struct qnode *
436431
spin_end();
437432

438433
preempted = true;
439-
seen_sleepy_node(lock, val);
434+
seen_sleepy_node();
440435

441436
smp_rmb(); /* See __yield_to_locked_owner comment */
442437

@@ -587,7 +582,8 @@ static __always_inline void queued_spin_lock_mcs_queue(struct qspinlock *lock, b
587582
* head of the waitqueue.
588583
*/
589584
if (old & _Q_TAIL_CPU_MASK) {
590-
struct qnode *prev = get_tail_qnode(lock, old);
585+
int prev_cpu = decode_tail_cpu(old);
586+
struct qnode *prev = get_tail_qnode(lock, prev_cpu);
591587

592588
/* Link @node into the waitqueue. */
593589
WRITE_ONCE(prev->next, node);
@@ -597,7 +593,7 @@ static __always_inline void queued_spin_lock_mcs_queue(struct qspinlock *lock, b
597593
while (!READ_ONCE(node->locked)) {
598594
spec_barrier();
599595

600-
if (yield_to_prev(lock, node, old, paravirt))
596+
if (yield_to_prev(lock, node, prev_cpu, paravirt))
601597
seen_preempted = true;
602598
}
603599
spec_barrier();

0 commit comments

Comments
 (0)