Re: rt_mutex_timed_lock() vs hrtimer_wakeup() race ?

Steven Rostedt
2006-07-31T20:47:53Z

On Tue, 2006-08-01 at 04:12 +0400, Oleg Nesterov wrote:
> On 07/30, Steven Rostedt wrote:
> >
> > On Sun, 2006-07-30 at 08:36 +0400, Oleg Nesterov wrote:
> > >
> > > Another question, task_blocks_on_rt_mutex() does get_task_struct() and checks
> > > owner->pi_blocked_on != NULL under owner->pi_lock. Why ? RT_MUTEX_HAS_WAITERS
> > > bit is set, we are holding ->wait_lock, so the 'owner' can't go away until
> > > we drop ->wait_lock.
> >
> > That's probably true that the owner can't disappear before we let go of
> > the wait_lock, since the owner should not be disappearing while holding
> > locks. But you are missing the point to why we are grabbing the
> > pi_lock. We are preventing a race that can have us do unneeded work
> > (see below).
>
> Yes, I see. But ...
>
> > ===================================================================
> > --- linux-2.6.18-rc2.orig/kernel/rtmutex.c 2006-07-30 18:04:12.000000000 -0400
> > +++ linux-2.6.18-rc2/kernel/rtmutex.c 2006-07-30 18:07:08.000000000 -0400
> > @@ -433,25 +433,26 @@ static int task_blocks_on_rt_mutex(struc
> > ...
> > else if (debug_rt_mutex_detect_deadlock(waiter, detect_deadlock)) {
> > spin_lock_irqsave(&owner->pi_lock, flags);
> > - if (owner->pi_blocked_on) {
> > + if (owner->pi_blocked_on)
> > boost = 1;
> > - /* gets dropped in rt_mutex_adjust_prio_chain()! */
> > - get_task_struct(owner);
> > - }
> > spin_unlock_irqrestore(&owner->pi_lock, flags);
>
> In that case ->pi_lock can't buy anything. With or without ->pi_lock this
> check is equally racy, so spin_lock() only adds unneeded work?

crap! I just did a blind change there. The first one does matter, but
this is for debugging. Hmm actually I would just remove the owner
blocked check all together and do the boost = 1 to force the chain walk.
It's for debugging anyway.

So that probably could just look something like this:

else if (debug_rt_mutex_detect_deadlock(waiter, detect_deadlock))
boost = 1;

the "boost" here is a misnomer. It probably would be better to call it
"walk" or "chain_walk".

-- Steve