| From: Mike Galbraith <efault@gmx.de> |
| Date: Fri, 18 Aug 2017 10:56:14 +0200 |
| Subject: [PATCH] locking, rwlock-rt: do not save state multiple times in |
| __write_rt_lock() |
| |
| Save state prior to entering the acquisition loop, otherwise we may |
| initially see readers, but upon releasing ->wait_lock see none, loop |
| back around, and having not slept, save TASK_UNINTERRUPTIBLE. |
| |
| Signed-off-by: Mike Galbraith <efault@gmx.de> |
| Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
| --- |
| kernel/locking/rwlock-rt.c | 18 ++++++++++++------ |
| 1 file changed, 12 insertions(+), 6 deletions(-) |
| |
| --- a/kernel/locking/rwlock-rt.c |
| +++ b/kernel/locking/rwlock-rt.c |
| @@ -190,14 +190,14 @@ void __sched __write_rt_lock(struct rt_r |
| /* Force readers into slow path */ |
| atomic_sub(READER_BIAS, &lock->readers); |
| |
| - for (;;) { |
| - raw_spin_lock_irqsave(&m->wait_lock, flags); |
| + raw_spin_lock_irqsave(&m->wait_lock, flags); |
| |
| - raw_spin_lock(&self->pi_lock); |
| - self->saved_state = self->state; |
| - __set_current_state_no_track(TASK_UNINTERRUPTIBLE); |
| - raw_spin_unlock(&self->pi_lock); |
| + raw_spin_lock(&self->pi_lock); |
| + self->saved_state = self->state; |
| + __set_current_state_no_track(TASK_UNINTERRUPTIBLE); |
| + raw_spin_unlock(&self->pi_lock); |
| |
| + for (;;) { |
| /* Have all readers left the critical region? */ |
| if (!atomic_read(&lock->readers)) { |
| atomic_set(&lock->readers, WRITER_BIAS); |
| @@ -213,6 +213,12 @@ void __sched __write_rt_lock(struct rt_r |
| |
| if (atomic_read(&lock->readers) != 0) |
| schedule(); |
| + |
| + raw_spin_lock_irqsave(&m->wait_lock, flags); |
| + |
| + raw_spin_lock(&self->pi_lock); |
| + __set_current_state_no_track(TASK_UNINTERRUPTIBLE); |
| + raw_spin_unlock(&self->pi_lock); |
| } |
| } |
| |