Currently is single pass, we can wait on idle_done instead wait on rebind_hold. So we can remove rebind_hold and make the code simpler.
Signed-off-by: Lai Jiangshan <la...@cn.fujitsu.com> --- kernel/workqueue.c | 35 +++++++++++------------------------ 1 files changed, 11 insertions(+), 24 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 6d68571..6411616 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1309,9 +1309,6 @@ struct idle_rebind { int idle_cnt; /* # idle workers to be rebound */ struct completion idle_done; /* all idle workers rebound */ - /* idle workers wait all idles to be rebound */ - struct completion rebind_hold; - /* * notify the rebind_workers() that: * 1. All idle workers are rebound. @@ -1340,7 +1337,7 @@ static void synchronize_all_idles_rebound(struct global_cwq *gcwq, { /* wait for rebind_workers() to notify that all idles are rebound */ - wait_for_completion(&idle_rebind->rebind_hold); + wait_for_completion(&idle_rebind->idle_done); /* finished synchronizing, put reference */ spin_lock_irq(&gcwq->lock); @@ -1371,7 +1368,7 @@ static void idle_worker_rebind(struct worker *worker) /* this worker has been rebound */ if (!--idle_rebind->idle_cnt) - complete(&idle_rebind->idle_done); + complete_all(&idle_rebind->idle_done); spin_unlock_irq(&gcwq->lock); synchronize_all_idles_rebound(gcwq, idle_rebind); @@ -1447,17 +1444,15 @@ static void rebind_workers(struct global_cwq *gcwq) lockdep_assert_held(&pool->manager_mutex); /* - * Rebind idle workers. Interlocked both ways in triple waits. - * We wait for workers to rebind via @idle_rebind.idle_done. - * Workers will wait for us via @idle_rebind.rebind_hold. - * And them we wait for workers to leave rebind_hold - * via @idle_rebind.ref_done. + * Rebind idle workers. Idle workers wait each other to rebind via + * synchronize_all_idles_rebound(). We wait for all idle workers + * to rebind via synchronize_all_idles_rebound() too. + * And them we wait for all workers finish synchronizing and + * release the ref of @idle_rebind via @idle_rebind.ref_done. */ init_completion(&idle_rebind.idle_done); - init_completion(&idle_rebind.rebind_hold); init_completion(&idle_rebind.ref_done); idle_rebind.ref_cnt = 1; - gcwq->idle_rebind = &idle_rebind; idle_rebind.idle_cnt = 1; /* set REBIND and kick idle ones, we'll wait for these later */ @@ -1497,23 +1492,15 @@ static void rebind_workers(struct global_cwq *gcwq) } /* - * we will leave rebind_workers(), have to wait until no worker - * has ref to this idle_rebind. + * we will leave rebind_workers(), have to wait until all idles + * are rebound and until no worker has ref to this idle_rebind. */ if (--idle_rebind.idle_cnt) { + gcwq->idle_rebind = &idle_rebind; spin_unlock_irq(&gcwq->lock); - wait_for_completion(&idle_rebind.idle_done); - spin_lock_irq(&gcwq->lock); - } - - complete_all(&idle_rebind.rebind_hold); - - if (--idle_rebind.ref_cnt) { - spin_unlock_irq(&gcwq->lock); + synchronize_all_idles_rebound(gcwq, &idle_rebind); wait_for_completion(&idle_rebind.ref_done); spin_lock_irq(&gcwq->lock); - } else { - gcwq->idle_rebind = NULL; } } -- 1.7.4.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/