]> git.karo-electronics.de Git - karo-tx-linux.git/commit
workqueue: consider work function when searching for busy work items
authorTejun Heo <tj@kernel.org>
Tue, 18 Dec 2012 18:35:02 +0000 (10:35 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 3 Mar 2013 22:03:38 +0000 (06:03 +0800)
commite50e7d633e76caf48ca5341a9679fcfdd1318d80
tree3b21091c3ae0f0e6d68193d6e3a72f7c1b85022d
parentc205ae0e166fa0fdfdfb2cb55a4fc597b0dd68be
workqueue: consider work function when searching for busy work items

commit a2c1c57be8d9fd5b716113c8991d3d702eeacf77 upstream.

To avoid executing the same work item concurrenlty, workqueue hashes
currently busy workers according to their current work items and looks
up the the table when it wants to execute a new work item.  If there
already is a worker which is executing the new work item, the new item
is queued to the found worker so that it gets executed only after the
current execution finishes.

Unfortunately, a work item may be freed while being executed and thus
recycled for different purposes.  If it gets recycled for a different
work item and queued while the previous execution is still in
progress, workqueue may make the new work item wait for the old one
although the two aren't really related in any way.

In extreme cases, this false dependency may lead to deadlock although
it's extremely unlikely given that there aren't too many self-freeing
work item users and they usually don't wait for other work items.

To alleviate the problem, record the current work function in each
busy worker and match it together with the work item address in
find_worker_executing_work().  While this isn't complete, it ensures
that unrelated work items don't interact with each other and in the
very unlikely case where a twisted wq user triggers it, it's always
onto itself making the culprit easy to spot.

Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-by: Andrey Isakov <andy51@gmx.ru>
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=51701
Cc: stable@vger.kernel.org
kernel/workqueue.c