Date: Thu, 15 May 2008 17:05:39 +0800 From: David Xu <davidxu@freebsd.org> To: Andriy Gapon <avg@icyb.net.ua> Cc: freebsd-stable@freebsd.org, Brent Casavant <b.j.casavant@ieee.org>, freebsd-threads@freebsd.org Subject: Re: thread scheduling at mutex unlock Message-ID: <482BFCE3.7080704@freebsd.org> In-Reply-To: <482BF5EA.5010806@icyb.net.ua> References: <482B0297.2050300@icyb.net.ua> <482BBA77.8000704@freebsd.org> <482BF5EA.5010806@icyb.net.ua>
next in thread | previous in thread | raw e-mail | index | archive | help
Andriy Gapon wrote:
> Brent, David,
>
> thank you for the responses.
> I think I incorrectly formulated my original concern.
> It is not about behavior at mutex unlock but about behavior at mutex
> re-lock. You are right that waking waiters at unlock would hurt
> performance. But I think that it is not "fair" that at re-lock former
> owner gets the lock immediately and the thread that waited on it for
> longer time doesn't get a chance.
>
> Here's a more realistic example than the mock up code.
> Say you have a worker thread that processes queued requests and the load
> is such that there is always something on the queue. Thus the worker
> thread doesn't ever have to block waiting on it.
> And let's say that there is a GUI thread that wants to convey some
> information to the worker thread. And for that it needs to acquire some
> mutex and "do something".
> With current libthr behavior the GUI thread would never have a chance to
> get the mutex as worker thread would always be a winner (as my small
> program shows).
> Or even more realistic: there should be a feeder thread that puts things
> on the queue, it would never be able to enqueue new items until the
> queue becomes empty if worker thread's code looks like the following:
>
> while(1)
> {
> pthread_mutex_lock(&work_mutex);
> while(queue.is_empty())
> pthread_cond_wait(...);
> //dequeue item
> ...
> pthread_mutex_unlock(&work mutex);
> //perform some short and non-blocking processing of the item
> ...
> }
>
> Because the worker thread (while the queue is not empty) would never
> enter cond_wait and would always re-lock the mutex shortly after
> unlocking it.
>
> So while improving performance on small scale this mutex re-acquire-ing
> unfairness may be hurting interactivity and thread concurrency and thus
> performance in general. E.g. in the above example queue would always be
> effectively of depth 1.
> Something about "lock starvation" comes to mind.
>
> So, yes, this is not about standards, this is about reasonable
> expectations about thread concurrency behavior in a particular
> implementation (libthr).
> I see now that performance advantage of libthr over libkse came with a
> price. I think that something like queued locks is needed. They would
> clearly reduce raw throughput performance, so maybe that should be a new
> (non-portable?) mutex attribute.
>
You forgot that default scheduling policy is time-sharing, after thread
#2 has blocked on the mutex for a while, when thread #1 unlocks the
mutex and unblocks thread #1, the thread #2's priority will be raised
and it preempts thread #1, the thread #2 then acquires the mutex,
that's how it balances between fairness and performance.
Regards,
David Xu
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?482BFCE3.7080704>
