[PATCH 09/10] workqueue: remove flusher_overflow
We can detect whether a flusher is started by comparing its flush_color VS wq->work_color. We move all overflowed flusher to flusher_queue, and then we start flush for them when there is freed color. we detect it by the color of the last flusher of the flusher_queue. This patch doesn't make any functional difference. Signed-off-by: Lai Jiangshan --- kernel/workqueue.c | 39 +-- 1 files changed, 13 insertions(+), 26 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index f687893..d78fe08 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -252,7 +252,6 @@ struct workqueue_struct { atomic_tnr_cwqs_to_flush[WORK_NR_COLORS]; struct wq_flusher *first_flusher; /* F: first flusher */ struct list_headflusher_queue; /* F: flush waiters */ - struct list_headflusher_overflow; /* F: flush overflow list */ mayday_mask_t mayday_mask;/* cpus requesting rescue */ struct worker *rescuer; /* I: rescue worker */ @@ -2600,7 +2599,7 @@ void flush_workqueue(struct workqueue_struct *wq) .flush_color = -1, .done = COMPLETION_INITIALIZER_ONSTACK(this_flusher.done), }; - struct wq_flusher *next, *tmp; + struct wq_flusher *next, *tmp, *last; int flush_color, next_color; lock_map_acquire(>lockdep_map); @@ -2617,8 +2616,6 @@ void flush_workqueue(struct workqueue_struct *wq) if (next_color != wq->flush_color) { /* Color space is not full */ - BUG_ON(!list_empty(>flusher_overflow)); - if (!wq->first_flusher) { /* no flush in progress, become the first flusher */ BUG_ON(wq->flush_color != flush_color); @@ -2642,11 +2639,11 @@ void flush_workqueue(struct workqueue_struct *wq) } } else { /* -* Oops, color space is full, wait on overflow queue. +* Oops, color space is full, queue it without starting flush. * The next flush completion will start flush for us -* with freed flush color and transfer us to flusher_queue. +* with freed flush color. */ - list_add_tail(_flusher.list, >flusher_overflow); + list_add_tail(_flusher.list, >flusher_queue); } mutex_unlock(>flush_mutex); @@ -2676,27 +2673,9 @@ void flush_workqueue(struct workqueue_struct *wq) complete(>done); } - BUG_ON(!list_empty(>flusher_overflow) && - wq->flush_color != work_next_color(wq->work_color)); - /* this flush_color is finished, advance by one */ wq->flush_color = work_next_color(wq->flush_color); - /* one color has been freed, handle overflow queue */ - if (!list_empty(>flusher_overflow)) { - BUG_ON(list_first_entry(>flusher_overflow, - struct wq_flusher, - list)->flush_color - != wq->work_color); - /* -* start flush with the freed color and append -* overflowed flushers to the flusher_queue. -*/ - list_splice_tail_init(>flusher_overflow, - >flusher_queue); - workqueue_start_flush(wq); - } - if (list_empty(>flusher_queue)) { BUG_ON(wq->flush_color != wq->work_color); wq->first_flusher = NULL; @@ -2710,8 +2689,17 @@ void flush_workqueue(struct workqueue_struct *wq) BUG_ON(wq->flush_color == wq->work_color); BUG_ON(wq->flush_color != next->flush_color); + last = list_entry(wq->flusher_queue.prev, struct wq_flusher, list); list_del_init(>list); wq->first_flusher = next; + + /* if have unstarted flushers appended, start flush for them */ + if (last->flush_color == wq->work_color) + workqueue_start_flush(wq); + + BUG_ON(work_next_color(last->flush_color) != wq->work_color); + + /* arm new first flusher */ wq_dec_flusher_ref(wq, wq->flush_color); out_unlock: @@ -3221,7 +3209,6 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt, for (color = 0; color < WORK_NR_COLORS; color++) atomic_set(>nr_cwqs_to_flush[color], 0); INIT_LIST_HEAD(>flusher_queue); - INIT_LIST_HEAD(>flusher_overflow); lockdep_init_map(>lockdep_map, lock_name, key, 0); INIT_LIST_HEAD(>list); -- 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/
[PATCH 09/10] workqueue: remove flusher_overflow
We can detect whether a flusher is started by comparing its flush_color VS wq-work_color. We move all overflowed flusher to flusher_queue, and then we start flush for them when there is freed color. we detect it by the color of the last flusher of the flusher_queue. This patch doesn't make any functional difference. Signed-off-by: Lai Jiangshan la...@cn.fujitsu.com --- kernel/workqueue.c | 39 +-- 1 files changed, 13 insertions(+), 26 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index f687893..d78fe08 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -252,7 +252,6 @@ struct workqueue_struct { atomic_tnr_cwqs_to_flush[WORK_NR_COLORS]; struct wq_flusher *first_flusher; /* F: first flusher */ struct list_headflusher_queue; /* F: flush waiters */ - struct list_headflusher_overflow; /* F: flush overflow list */ mayday_mask_t mayday_mask;/* cpus requesting rescue */ struct worker *rescuer; /* I: rescue worker */ @@ -2600,7 +2599,7 @@ void flush_workqueue(struct workqueue_struct *wq) .flush_color = -1, .done = COMPLETION_INITIALIZER_ONSTACK(this_flusher.done), }; - struct wq_flusher *next, *tmp; + struct wq_flusher *next, *tmp, *last; int flush_color, next_color; lock_map_acquire(wq-lockdep_map); @@ -2617,8 +2616,6 @@ void flush_workqueue(struct workqueue_struct *wq) if (next_color != wq-flush_color) { /* Color space is not full */ - BUG_ON(!list_empty(wq-flusher_overflow)); - if (!wq-first_flusher) { /* no flush in progress, become the first flusher */ BUG_ON(wq-flush_color != flush_color); @@ -2642,11 +2639,11 @@ void flush_workqueue(struct workqueue_struct *wq) } } else { /* -* Oops, color space is full, wait on overflow queue. +* Oops, color space is full, queue it without starting flush. * The next flush completion will start flush for us -* with freed flush color and transfer us to flusher_queue. +* with freed flush color. */ - list_add_tail(this_flusher.list, wq-flusher_overflow); + list_add_tail(this_flusher.list, wq-flusher_queue); } mutex_unlock(wq-flush_mutex); @@ -2676,27 +2673,9 @@ void flush_workqueue(struct workqueue_struct *wq) complete(next-done); } - BUG_ON(!list_empty(wq-flusher_overflow) - wq-flush_color != work_next_color(wq-work_color)); - /* this flush_color is finished, advance by one */ wq-flush_color = work_next_color(wq-flush_color); - /* one color has been freed, handle overflow queue */ - if (!list_empty(wq-flusher_overflow)) { - BUG_ON(list_first_entry(wq-flusher_overflow, - struct wq_flusher, - list)-flush_color - != wq-work_color); - /* -* start flush with the freed color and append -* overflowed flushers to the flusher_queue. -*/ - list_splice_tail_init(wq-flusher_overflow, - wq-flusher_queue); - workqueue_start_flush(wq); - } - if (list_empty(wq-flusher_queue)) { BUG_ON(wq-flush_color != wq-work_color); wq-first_flusher = NULL; @@ -2710,8 +2689,17 @@ void flush_workqueue(struct workqueue_struct *wq) BUG_ON(wq-flush_color == wq-work_color); BUG_ON(wq-flush_color != next-flush_color); + last = list_entry(wq-flusher_queue.prev, struct wq_flusher, list); list_del_init(next-list); wq-first_flusher = next; + + /* if have unstarted flushers appended, start flush for them */ + if (last-flush_color == wq-work_color) + workqueue_start_flush(wq); + + BUG_ON(work_next_color(last-flush_color) != wq-work_color); + + /* arm new first flusher */ wq_dec_flusher_ref(wq, wq-flush_color); out_unlock: @@ -3221,7 +3209,6 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt, for (color = 0; color WORK_NR_COLORS; color++) atomic_set(wq-nr_cwqs_to_flush[color], 0); INIT_LIST_HEAD(wq-flusher_queue); - INIT_LIST_HEAD(wq-flusher_overflow); lockdep_init_map(wq-lockdep_map, lock_name, key, 0); INIT_LIST_HEAD(wq-list); -- 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