The code like if (is_single_threaded(wq)) do_something(singlethread_cpu); else { for_each_cpu_mask(cpu, cpu_populated_map) do_something(cpu); } looks very annoying. We can add "static cpumask_t cpu_singlethread_map" and simplify the code. Lessens .text a bit, and imho makes the code more readable.
Showing the changes to kernel/workqueue.c (1 of 1 file). Show all
Unified · Split
| @@ -69,6 +69,7 @@ static DEFINE_MUTEX(workqueue_mutex); · 68 unmodified lines | ||
| 69 | 69 | static LIST_HEAD(workqueues); |
| 70 | 70 | |
| 71 | 71 | static int singlethread_cpu __read_mostly; |
| 72 | +static cpumask_t cpu_singlethread_map __read_mostly; | |
| 72 | 73 | /* optimization, we could use cpu_possible_map */ |
| 73 | 74 | static cpumask_t cpu_populated_map __read_mostly; |
| 74 | 75 | |
| @@ -78,6 +79,12 @@ static inline int is_single_threaded(struct workqueue_struct *wq) · 3 unmodified lines | ||
| 78 | 79 | return list_empty(&wq->list); |
| 79 | 80 | } |
| 80 | 81 | |
| 82 | +static const cpumask_t *wq_cpu_map(struct workqueue_struct *wq) | |
| 83 | +{ | |
| 84 | + return is_single_threaded(wq) | |
| 85 | + ? &cpu_singlethread_map : &cpu_populated_map; | |
| 86 | +} | |
| 87 | + | |
| 81 | 88 | /* |
| 82 | 89 | * Set the workqueue on which a work item is to be run |
| 83 | 90 | * - Must *only* be called if the pending flag is set |
| @@ -393,16 +400,12 @@ static void flush_cpu_workqueue(struct cpu_workqueue_struct *cwq) · 309 unmodified lines | ||
| 393 | 400 | */ |
| 394 | 401 | void fastcall flush_workqueue(struct workqueue_struct *wq) |
| 395 | 402 | { |
| 396 | − might_sleep(); | |
| 397 | − | |
| 398 | − if (is_single_threaded(wq)) | |
| 399 | − flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, singlethread_cpu)); | |
| 400 | − else { | |
| 401 | − int cpu; | |
| 403 | + const cpumask_t *cpu_map = wq_cpu_map(wq); | |
| 404 | + int cpu | |
| 402 | 405 | |
| 403 | − for_each_cpu_mask(cpu, cpu_populated_map) | |
| 404 | − flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, cpu)); | |
| 405 | − } | |
| 406 | + might_sleep(); | |
| 407 | + for_each_cpu_mask(cpu, *cpu_map) | |
| 408 | + flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, cpu)); | |
| 406 | 409 | } |
| 407 | 410 | EXPORT_SYMBOL_GPL(flush_workqueue); |
| 408 | 411 | |
| @@ -439,7 +442,9 @@ static void wait_on_work(struct cpu_workqueue_struct *cwq, · 30 unmodified lines | ||
| 439 | 442 | */ |
| 440 | 443 | void flush_work(struct workqueue_struct *wq, struct work_struct *work) |
| 441 | 444 | { |
| 445 | + const cpumask_t *cpu_map = wq_cpu_map(wq); | |
| 442 | 446 | struct cpu_workqueue_struct *cwq; |
| 447 | + int cpu; | |
| 443 | 448 | |
| 444 | 449 | might_sleep(); |
| 445 | 450 | |
| @@ -457,14 +462,8 @@ void flush_work(struct workqueue_struct *wq, struct work_struct *work) · 11 unmodified lines | ||
| 457 | 462 | work_release(work); |
| 458 | 463 | spin_unlock_irq(&cwq->lock); |
| 459 | 464 | |
| 460 | − if (is_single_threaded(wq)) | |
| 461 | − wait_on_work(per_cpu_ptr(wq->cpu_wq, singlethread_cpu), work); | |
| 462 | − else { | |
| 463 | − int cpu; | |
| 464 | − | |
| 465 | − for_each_cpu_mask(cpu, cpu_populated_map) | |
| 466 | − wait_on_work(per_cpu_ptr(wq->cpu_wq, cpu), work); | |
| 467 | − } | |
| 465 | + for_each_cpu_mask(cpu, *cpu_map) | |
| 466 | + wait_on_work(per_cpu_ptr(wq->cpu_wq, cpu), work); | |
| 468 | 467 | } |
| 469 | 468 | EXPORT_SYMBOL_GPL(flush_work); |
| 470 | 469 | |
| @@ -757,22 +756,17 @@ static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu) · 286 unmodified lines | ||
| 757 | 756 | */ |
| 758 | 757 | void destroy_workqueue(struct workqueue_struct *wq) |
| 759 | 758 | { |
| 759 | + const cpumask_t *cpu_map = wq_cpu_map(wq); | |
| 760 | 760 | struct cpu_workqueue_struct *cwq; |
| 761 | + int cpu; | |
| 761 | 762 | |
| 762 | − if (is_single_threaded(wq)) { | |
| 763 | − cwq = per_cpu_ptr(wq->cpu_wq, singlethread_cpu); | |
| 764 | − cleanup_workqueue_thread(cwq, singlethread_cpu); | |
| 765 | − } else { | |
| 766 | − int cpu; | |
| 763 | + mutex_lock(&workqueue_mutex); | |
| 764 | + list_del(&wq->list); | |
| 765 | + mutex_unlock(&workqueue_mutex); | |
| 767 | 766 | |
| 768 | − mutex_lock(&workqueue_mutex); | |
| 769 | − list_del(&wq->list); | |
| 770 | − mutex_unlock(&workqueue_mutex); | |
| 771 | − | |
| 772 | − for_each_cpu_mask(cpu, cpu_populated_map) { | |
| 773 | − cwq = per_cpu_ptr(wq->cpu_wq, cpu); | |
| 774 | − cleanup_workqueue_thread(cwq, cpu); | |
| 775 | − } | |
| 767 | + for_each_cpu_mask(cpu, *cpu_map) { | |
| 768 | + cwq = per_cpu_ptr(wq->cpu_wq, cpu); | |
| 769 | + cleanup_workqueue_thread(cwq, cpu); | |
| 776 | 770 | } |
| 777 | 771 | |
| 778 | 772 | free_percpu(wq->cpu_wq); |
| @@ -831,6 +825,7 @@ void init_workqueues(void) · 52 unmodified lines | ||
| 831 | 825 | { |
| 832 | 826 | cpu_populated_map = cpu_online_map; |
| 833 | 827 | singlethread_cpu = first_cpu(cpu_possible_map); |
| 828 | + cpu_singlethread_map = cpumask_of_cpu(singlethread_cpu); | |
| 834 | 829 | hotcpu_notifier(workqueue_cpu_callback, 0); |
| 835 | 830 | keventd_wq = create_workqueue("events"); |
| 836 | 831 | BUG_ON(!keventd_wq); |