Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 03 Oct 2012 17:05:19 +0300
From:      Andriy Gapon <avg@FreeBSD.org>
To:        attilio@FreeBSD.org
Cc:        freebsd-hackers <freebsd-hackers@FreeBSD.org>, Jeff Roberson <jeff@FreeBSD.org>
Subject:   Re: ule+smp: small optimization for turnstile priority lending
Message-ID:  <506C461F.2050008@FreeBSD.org>
In-Reply-To: <CAJ-FndAiiH5ToUtns=jC7_V27BkeOvJ8_T9SOmw2DGdFyfvTdg@mail.gmail.com>
References:  <50587F8D.9060102@FreeBSD.org> <CAJ-FndCWzTBRYsA0mFDCj8RU06ZUTi3G0LeEFcS9_c5zKd%2BgWQ@mail.gmail.com> <5058C68B.1010508@FreeBSD.org> <CAJ-FndC8j12a95N0QprYTLJLC06R8jjcaHuxEZKu5D9RHW=ZVw@mail.gmail.com> <50596019.5060708@FreeBSD.org> <CAJ-FndBxWYOkRCn-DZTdZ%2BB4RpvsvaxtwDyMc8M7YhRj9DaL2w@mail.gmail.com> <505AF836.7050004@FreeBSD.org> <CAJ-FndAiiH5ToUtns=jC7_V27BkeOvJ8_T9SOmw2DGdFyfvTdg@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
on 20/09/2012 16:14 Attilio Rao said the following:
> On 9/20/12, Andriy Gapon <avg@freebsd.org> wrote:
[snip]
>> The patch works well as far as I can tell.  Thank you!
>> There is one warning with full witness enables but it appears to be harmless
>> (so
>> far):
> 
> Andriy,
> thanks a lot for your testing and reports you made so far.
> Unfortunately I'm going off for 2 weeks now and I won't work on
> FreeBSD for that timeframe. I will get back to those in 2 weeks then.
> If you want  to play more with this idea feel free to extend/fix/etc.
> this patch.

Unfortunately I haven't found time to work on this further, but I have some
additional thoughts.

First, I think that the witness message was not benign and it actually warns about
the same kind of deadlock that I originally had.
The problem is that sched_lend_prio() is called with target thread's td_lock held,
which is a lock of tdq on the thread's CPU.  Then, in your patch, we acquire
current tdq's lock to modify its load.  But if two tdq locks are to be held at the
same time, then they must be locked using tdq_lock_pair, so that lock order is
maintained.  With the patch no tdq lock order can be maintained (can arbitrary)
and thus it is possible to run into a deadlock.

I see two possibilities here, but don't rule out that there can be more.

1. Do something like my patch does.  That is, manipulate current thread's tdq in
advance before any other thread/tdq locks are acquired (or td_lock is changed to
point to a different lock and current tdq is unlocked).  The API can be made more
generic in nature.  E.g. it can look like this:
void
sched_thread_block(struct thread *td, int inhibitor)
{
	struct tdq *tdq;

	THREAD_LOCK_ASSERT(td, MA_OWNED);
	KASSERT(td == curthread,
	    ("sched_thread_block: only curthread is supported"));
	tdq = TDQ_SELF();
	TDQ_LOCK_ASSERT(tdq, MA_OWNED);
	MPASS(td->td_lock == TDQ_LOCKPTR(tdq));
	TD_SET_INHIB(td, inhibitor);
	tdq_load_rem(tdq, td);
	tdq_setlowpri(tdq, td);
}


2. Try to do things from sched_lend_prio based on curthread's state.  This, as it
seems, would require completely lock-less manipulations of current tdq.  E.g. for
tdq_load we could use atomic operations (it is already accessed locklessly, but
not modified).  But for tdq_lowpri a more elaborate trick would be required like
having a separate field for a temporary value.

In any case, I'll have to revisit this later.

-- 
Andriy Gapon



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?506C461F.2050008>