On Fri, May 10, 2019 at 11:28 AM Petr Mladek <pmladek@xxxxxxxx> wrote: > > On Thu 2019-05-09 22:06:33, Daniel Vetter wrote: > > console_trylock, called from within printk, can be called from pretty > > much anywhere. Including try_to_wake_up. Note that this isn't common, > > usually the box is in pretty bad shape at that point already. But it > > really doesn't help when then lockdep jumps in and spams the logs, > > potentially obscuring the real backtrace we're really interested in. > > One case I've seen (slightly simplified backtrace): > > > > Fix this specific locking recursion by moving the wake_up_process out > > from under the semaphore.lock spinlock, using wake_q as recommended by > > Peter Zijlstra. > > It might make sense to mention also the optimization effect mentioned > by Peter. > > > diff --git a/kernel/locking/semaphore.c b/kernel/locking/semaphore.c > > index 561acdd39960..7a6f33715688 100644 > > --- a/kernel/locking/semaphore.c > > +++ b/kernel/locking/semaphore.c > > @@ -169,6 +169,14 @@ int down_timeout(struct semaphore *sem, long timeout) > > } > > EXPORT_SYMBOL(down_timeout); > > > > +/* Functions for the contended case */ > > + > > +struct semaphore_waiter { > > + struct list_head list; > > + struct task_struct *task; > > + bool up; > > +}; > > + > > /** > > * up - release the semaphore > > * @sem: the semaphore to release > > @@ -179,24 +187,25 @@ EXPORT_SYMBOL(down_timeout); > > void up(struct semaphore *sem) > > { > > unsigned long flags; > > + struct semaphore_waiter *waiter; > > + DEFINE_WAKE_Q(wake_q); > > We need to call wake_q_init(&wake_q) to make sure that > it is empty. DEFINE_WAKE_Q does that already, and if it didn't, I'd wonder how I managed to boot with this patch. console_lock is usally terribly contented because thanks to fbcon we must do a full display modeset while holding it, which takes forever. As long as anyone printks meanwhile (guaranteed while loading drivers really) you have contention. -Daniel > Best Regards, > Petr > > > raw_spin_lock_irqsave(&sem->lock, flags); > > - if (likely(list_empty(&sem->wait_list))) > > + if (likely(list_empty(&sem->wait_list))) { > > sem->count++; > > - else > > - __up(sem); > > + } else { > > + waiter = list_first_entry(&sem->wait_list, > > + struct semaphore_waiter, list); > > + list_del(&waiter->list); > > + waiter->up = true; > > + wake_q_add(&wake_q, waiter->task); > > + } > > raw_spin_unlock_irqrestore(&sem->lock, flags); > > + > > + wake_up_q(&wake_q); > > } > > EXPORT_SYMBOL(up); > > > > -/* Functions for the contended case */ > > - > > -struct semaphore_waiter { > > - struct list_head list; > > - struct task_struct *task; > > - bool up; > > -}; > > - > > /* > > * Because this function is inlined, the 'state' parameter will be > > * constant, and thus optimised away by the compiler. Likewise the -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel