workqueue: implement @drain for workqueue_set_max_active()

workqueue_set_max_active() currently doesn't wait for the number of
in-flight work items to fall under the new @max_active.  This patch
adds @drain paramter to workqueue_set_max_active(), if set, the
function sleeps until nr_active on each pool_workqueue of the target
workqueue drops below the current saved_max_active.

This is planned to replace freezable workqueues.  It is determined
that kernel freezables - both kthreads and workqueues - aren't
necessary and just add to the confusion and unnecessary deadlocks.
There are only a handful which actually need to stop processing for
system power events and they can be converted to use
workqueue_set_max_active(WQ_FROZEN_ACTIVE) instead of freezable
workqueues.  Ultimately, all other uses of freezables will be dropped
and the whole system freezer machinery will be excised.  Well, that's
the plan anyway.

The implementation is fairly straight-forward.  As this is expected to
be used by only a handful and most likely not concurrently, a single
wait queue is used.  set_max_active drainers wait on it as necessary
and pwq_dec_nr_in_flight() triggers it if nr_active == max_active
after nr_active is decremented.  This unfortunately adds on unlikely
branch to the work item execution path but this is extremely unlikely
to be noticeable and I think it's worthwhile to avoid polling here as
there may be multiple calls to this function in succession during
suspend and some platforms use suspend quite frequently.

Signed-off-by: Tejun Heo <tj@kernel.org>
Link: http://lkml.kernel.org/g/20131218213936.GA8218@mtj.dyndns.org
Cc: Lai Jiangshan <laijs@cn.fujitsu.com>
Cc: David Howells <dhowells@redhat.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
3 files changed