• Lai Jiangshan's avatar
    workqueue: reimplement idle worker rebinding · ea1abd61
    Lai Jiangshan authored
    Currently rebind_workers() uses rebinds idle workers synchronously
    before proceeding to requesting busy workers to rebind.  This is
    necessary because all workers on @worker_pool->idle_list must be bound
    before concurrency management local wake-ups from the busy workers
    take place.
    
    Unfortunately, the synchronous idle rebinding is quite complicated.
    This patch reimplements idle rebinding to simplify the code path.
    
    Rather than trying to make all idle workers bound before rebinding
    busy workers, we simply remove all to-be-bound idle workers from the
    idle list and let them add themselves back after completing rebinding
    (successful or not).
    
    As only workers which finished rebinding can on on the idle worker
    list, the idle worker list is guaranteed to have only bound workers
    unless CPU went down again and local wake-ups are safe.
    
    After the change, @worker_pool->nr_idle may deviate than the actual
    number of idle workers on @worker_pool->idle_list.  More specifically,
    nr_idle may be non-zero while ->idle_list is empty.  All users of
    ->nr_idle and ->idle_list are audited.  The only affected one is
    too_many_workers() which is updated to check %false if ->idle_list is
    empty regardless of ->nr_idle.
    
    After this patch, rebind_workers() no longer performs the nasty
    idle-rebind retries which require temporary release of gcwq->lock, and
    both unbinding and rebinding are atomic w.r.t. global_cwq->lock.
    
    worker->idle_rebind and global_cwq->rebind_hold are now unnecessary
    and removed along with the definition of struct idle_rebind.
    
    Changed from V1:
    	1) remove unlikely from too_many_workers(), ->idle_list can be empty
    	   anytime, even before this patch, no reason to use unlikely.
    	2) fix a small rebasing mistake.
    	   (which is from rebasing the orignal fixing patch to for-next)
    	3) add a lot of comments.
    	4) clear WORKER_REBIND unconditionaly in idle_worker_rebind()
    
    tj: Updated comments and description.
    Signed-off-by: default avatarLai Jiangshan <laijs@cn.fujitsu.com>
    Signed-off-by: default avatarTejun Heo <tj@kernel.org>
    ea1abd61
workqueue.c 107 KB