aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/workqueue.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2010-07-02 04:03:51 -0400
committerTejun Heo <tj@kernel.org>2010-07-02 04:59:57 -0400
commitbdbc5dd7de5d07d6c9d3536e598956165a031d4c (patch)
tree1f0f263126c2fc2e07a032df1e9ad3fecb534c9a /kernel/workqueue.c
parentad72cf9885c536e3adae03f8337557ac9dd1e4bb (diff)
workqueue: prepare for WQ_UNBOUND implementation
In preparation of WQ_UNBOUND addition, make the following changes. * Add WORK_CPU_* constants for pseudo cpu id numbers used (currently only WORK_CPU_NONE) and use them instead of NR_CPUS. This is to allow another pseudo cpu id for unbound cpu. * Reorder WQ_* flags. * Make workqueue_struct->cpu_wq a union which contains a percpu pointer, regular pointer and an unsigned long value and use kzalloc/kfree() in UP allocation path. This will be used to implement unbound workqueues which will use only one cwq on SMPs. * Move alloc_cwqs() allocation after initialization of wq fields, so that alloc_cwqs() has access to wq->flags. * Trivial relocation of wq local variables in freeze functions. These changes don't cause any functional change. Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r--kernel/workqueue.c83
1 files changed, 43 insertions, 40 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 2eb9fbddf5c6..a105ddf55f79 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -190,7 +190,11 @@ struct wq_flusher {
190 */ 190 */
191struct workqueue_struct { 191struct workqueue_struct {
192 unsigned int flags; /* I: WQ_* flags */ 192 unsigned int flags; /* I: WQ_* flags */
193 struct cpu_workqueue_struct *cpu_wq; /* I: cwq's */ 193 union {
194 struct cpu_workqueue_struct __percpu *pcpu;
195 struct cpu_workqueue_struct *single;
196 unsigned long v;
197 } cpu_wq; /* I: cwq's */
194 struct list_head list; /* W: list of all workqueues */ 198 struct list_head list; /* W: list of all workqueues */
195 199
196 struct mutex flush_mutex; /* protects wq flushing */ 200 struct mutex flush_mutex; /* protects wq flushing */
@@ -362,7 +366,11 @@ static atomic_t *get_gcwq_nr_running(unsigned int cpu)
362static struct cpu_workqueue_struct *get_cwq(unsigned int cpu, 366static struct cpu_workqueue_struct *get_cwq(unsigned int cpu,
363 struct workqueue_struct *wq) 367 struct workqueue_struct *wq)
364{ 368{
365 return per_cpu_ptr(wq->cpu_wq, cpu); 369#ifndef CONFIG_SMP
370 return wq->cpu_wq.single;
371#else
372 return per_cpu_ptr(wq->cpu_wq.pcpu, cpu);
373#endif
366} 374}
367 375
368static unsigned int work_color_to_flags(int color) 376static unsigned int work_color_to_flags(int color)
@@ -442,7 +450,7 @@ static struct global_cwq *get_work_gcwq(struct work_struct *work)
442 return ((struct cpu_workqueue_struct *)data)->gcwq; 450 return ((struct cpu_workqueue_struct *)data)->gcwq;
443 451
444 cpu = data >> WORK_STRUCT_FLAG_BITS; 452 cpu = data >> WORK_STRUCT_FLAG_BITS;
445 if (cpu == NR_CPUS) 453 if (cpu == WORK_CPU_NONE)
446 return NULL; 454 return NULL;
447 455
448 BUG_ON(cpu >= nr_cpu_ids); 456 BUG_ON(cpu >= nr_cpu_ids);
@@ -846,7 +854,7 @@ static void cwq_unbind_single_cpu(struct cpu_workqueue_struct *cwq)
846 */ 854 */
847 if (likely(!(gcwq->flags & GCWQ_FREEZING))) { 855 if (likely(!(gcwq->flags & GCWQ_FREEZING))) {
848 smp_wmb(); /* paired with cmpxchg() in __queue_work() */ 856 smp_wmb(); /* paired with cmpxchg() in __queue_work() */
849 wq->single_cpu = NR_CPUS; 857 wq->single_cpu = WORK_CPU_NONE;
850 } 858 }
851} 859}
852 860
@@ -904,7 +912,7 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq,
904 */ 912 */
905 retry: 913 retry:
906 cpu = wq->single_cpu; 914 cpu = wq->single_cpu;
907 arbitrate = cpu == NR_CPUS; 915 arbitrate = cpu == WORK_CPU_NONE;
908 if (arbitrate) 916 if (arbitrate)
909 cpu = req_cpu; 917 cpu = req_cpu;
910 918
@@ -918,7 +926,7 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq,
918 * visible on the new cpu after this point. 926 * visible on the new cpu after this point.
919 */ 927 */
920 if (arbitrate) 928 if (arbitrate)
921 cmpxchg(&wq->single_cpu, NR_CPUS, cpu); 929 cmpxchg(&wq->single_cpu, WORK_CPU_NONE, cpu);
922 930
923 if (unlikely(wq->single_cpu != cpu)) { 931 if (unlikely(wq->single_cpu != cpu)) {
924 spin_unlock_irqrestore(&gcwq->lock, flags); 932 spin_unlock_irqrestore(&gcwq->lock, flags);
@@ -2572,7 +2580,7 @@ int keventd_up(void)
2572 return system_wq != NULL; 2580 return system_wq != NULL;
2573} 2581}
2574 2582
2575static struct cpu_workqueue_struct *alloc_cwqs(void) 2583static int alloc_cwqs(struct workqueue_struct *wq)
2576{ 2584{
2577 /* 2585 /*
2578 * cwqs are forced aligned according to WORK_STRUCT_FLAG_BITS. 2586 * cwqs are forced aligned according to WORK_STRUCT_FLAG_BITS.
@@ -2582,40 +2590,36 @@ static struct cpu_workqueue_struct *alloc_cwqs(void)
2582 const size_t size = sizeof(struct cpu_workqueue_struct); 2590 const size_t size = sizeof(struct cpu_workqueue_struct);
2583 const size_t align = max_t(size_t, 1 << WORK_STRUCT_FLAG_BITS, 2591 const size_t align = max_t(size_t, 1 << WORK_STRUCT_FLAG_BITS,
2584 __alignof__(unsigned long long)); 2592 __alignof__(unsigned long long));
2585 struct cpu_workqueue_struct *cwqs;
2586#ifndef CONFIG_SMP 2593#ifndef CONFIG_SMP
2587 void *ptr; 2594 void *ptr;
2588 2595
2589 /* 2596 /*
2590 * On UP, percpu allocator doesn't honor alignment parameter 2597 * Allocate enough room to align cwq and put an extra pointer
2591 * and simply uses arch-dependent default. Allocate enough 2598 * at the end pointing back to the originally allocated
2592 * room to align cwq and put an extra pointer at the end 2599 * pointer which will be used for free.
2593 * pointing back to the originally allocated pointer which
2594 * will be used for free.
2595 *
2596 * FIXME: This really belongs to UP percpu code. Update UP
2597 * percpu code to honor alignment and remove this ugliness.
2598 */ 2600 */
2599 ptr = __alloc_percpu(size + align + sizeof(void *), 1); 2601 ptr = kzalloc(size + align + sizeof(void *), GFP_KERNEL);
2600 cwqs = PTR_ALIGN(ptr, align); 2602 if (ptr) {
2601 *(void **)per_cpu_ptr(cwqs + 1, 0) = ptr; 2603 wq->cpu_wq.single = PTR_ALIGN(ptr, align);
2604 *(void **)(wq->cpu_wq.single + 1) = ptr;
2605 }
2602#else 2606#else
2603 /* On SMP, percpu allocator can do it itself */ 2607 /* On SMP, percpu allocator can align itself */
2604 cwqs = __alloc_percpu(size, align); 2608 wq->cpu_wq.pcpu = __alloc_percpu(size, align);
2605#endif 2609#endif
2606 /* just in case, make sure it's actually aligned */ 2610 /* just in case, make sure it's actually aligned */
2607 BUG_ON(!IS_ALIGNED((unsigned long)cwqs, align)); 2611 BUG_ON(!IS_ALIGNED(wq->cpu_wq.v, align));
2608 return cwqs; 2612 return wq->cpu_wq.v ? 0 : -ENOMEM;
2609} 2613}
2610 2614
2611static void free_cwqs(struct cpu_workqueue_struct *cwqs) 2615static void free_cwqs(struct workqueue_struct *wq)
2612{ 2616{
2613#ifndef CONFIG_SMP 2617#ifndef CONFIG_SMP
2614 /* on UP, the pointer to free is stored right after the cwq */ 2618 /* on UP, the pointer to free is stored right after the cwq */
2615 if (cwqs) 2619 if (wq->cpu_wq.single)
2616 free_percpu(*(void **)per_cpu_ptr(cwqs + 1, 0)); 2620 kfree(*(void **)(wq->cpu_wq.single + 1));
2617#else 2621#else
2618 free_percpu(cwqs); 2622 free_percpu(wq->cpu_wq.pcpu);
2619#endif 2623#endif
2620} 2624}
2621 2625
@@ -2645,22 +2649,21 @@ struct workqueue_struct *__alloc_workqueue_key(const char *name,
2645 if (!wq) 2649 if (!wq)
2646 goto err; 2650 goto err;
2647 2651
2648 wq->cpu_wq = alloc_cwqs();
2649 if (!wq->cpu_wq)
2650 goto err;
2651
2652 wq->flags = flags; 2652 wq->flags = flags;
2653 wq->saved_max_active = max_active; 2653 wq->saved_max_active = max_active;
2654 mutex_init(&wq->flush_mutex); 2654 mutex_init(&wq->flush_mutex);
2655 atomic_set(&wq->nr_cwqs_to_flush, 0); 2655 atomic_set(&wq->nr_cwqs_to_flush, 0);
2656 INIT_LIST_HEAD(&wq->flusher_queue); 2656 INIT_LIST_HEAD(&wq->flusher_queue);
2657 INIT_LIST_HEAD(&wq->flusher_overflow); 2657 INIT_LIST_HEAD(&wq->flusher_overflow);
2658 wq->single_cpu = NR_CPUS; 2658 wq->single_cpu = WORK_CPU_NONE;
2659 2659
2660 wq->name = name; 2660 wq->name = name;
2661 lockdep_init_map(&wq->lockdep_map, lock_name, key, 0); 2661 lockdep_init_map(&wq->lockdep_map, lock_name, key, 0);
2662 INIT_LIST_HEAD(&wq->list); 2662 INIT_LIST_HEAD(&wq->list);
2663 2663
2664 if (alloc_cwqs(wq) < 0)
2665 goto err;
2666
2664 for_each_possible_cpu(cpu) { 2667 for_each_possible_cpu(cpu) {
2665 struct cpu_workqueue_struct *cwq = get_cwq(cpu, wq); 2668 struct cpu_workqueue_struct *cwq = get_cwq(cpu, wq);
2666 struct global_cwq *gcwq = get_gcwq(cpu); 2669 struct global_cwq *gcwq = get_gcwq(cpu);
@@ -2710,7 +2713,7 @@ struct workqueue_struct *__alloc_workqueue_key(const char *name,
2710 return wq; 2713 return wq;
2711err: 2714err:
2712 if (wq) { 2715 if (wq) {
2713 free_cwqs(wq->cpu_wq); 2716 free_cwqs(wq);
2714 free_cpumask_var(wq->mayday_mask); 2717 free_cpumask_var(wq->mayday_mask);
2715 kfree(wq->rescuer); 2718 kfree(wq->rescuer);
2716 kfree(wq); 2719 kfree(wq);
@@ -2755,7 +2758,7 @@ void destroy_workqueue(struct workqueue_struct *wq)
2755 free_cpumask_var(wq->mayday_mask); 2758 free_cpumask_var(wq->mayday_mask);
2756 } 2759 }
2757 2760
2758 free_cwqs(wq->cpu_wq); 2761 free_cwqs(wq);
2759 kfree(wq); 2762 kfree(wq);
2760} 2763}
2761EXPORT_SYMBOL_GPL(destroy_workqueue); 2764EXPORT_SYMBOL_GPL(destroy_workqueue);
@@ -2821,13 +2824,13 @@ EXPORT_SYMBOL_GPL(workqueue_congested);
2821 * @work: the work of interest 2824 * @work: the work of interest
2822 * 2825 *
2823 * RETURNS: 2826 * RETURNS:
2824 * CPU number if @work was ever queued. NR_CPUS otherwise. 2827 * CPU number if @work was ever queued. WORK_CPU_NONE otherwise.
2825 */ 2828 */
2826unsigned int work_cpu(struct work_struct *work) 2829unsigned int work_cpu(struct work_struct *work)
2827{ 2830{
2828 struct global_cwq *gcwq = get_work_gcwq(work); 2831 struct global_cwq *gcwq = get_work_gcwq(work);
2829 2832
2830 return gcwq ? gcwq->cpu : NR_CPUS; 2833 return gcwq ? gcwq->cpu : WORK_CPU_NONE;
2831} 2834}
2832EXPORT_SYMBOL_GPL(work_cpu); 2835EXPORT_SYMBOL_GPL(work_cpu);
2833 2836
@@ -3300,7 +3303,6 @@ EXPORT_SYMBOL_GPL(work_on_cpu);
3300 */ 3303 */
3301void freeze_workqueues_begin(void) 3304void freeze_workqueues_begin(void)
3302{ 3305{
3303 struct workqueue_struct *wq;
3304 unsigned int cpu; 3306 unsigned int cpu;
3305 3307
3306 spin_lock(&workqueue_lock); 3308 spin_lock(&workqueue_lock);
@@ -3310,6 +3312,7 @@ void freeze_workqueues_begin(void)
3310 3312
3311 for_each_possible_cpu(cpu) { 3313 for_each_possible_cpu(cpu) {
3312 struct global_cwq *gcwq = get_gcwq(cpu); 3314 struct global_cwq *gcwq = get_gcwq(cpu);
3315 struct workqueue_struct *wq;
3313 3316
3314 spin_lock_irq(&gcwq->lock); 3317 spin_lock_irq(&gcwq->lock);
3315 3318
@@ -3344,7 +3347,6 @@ void freeze_workqueues_begin(void)
3344 */ 3347 */
3345bool freeze_workqueues_busy(void) 3348bool freeze_workqueues_busy(void)
3346{ 3349{
3347 struct workqueue_struct *wq;
3348 unsigned int cpu; 3350 unsigned int cpu;
3349 bool busy = false; 3351 bool busy = false;
3350 3352
@@ -3353,6 +3355,7 @@ bool freeze_workqueues_busy(void)
3353 BUG_ON(!workqueue_freezing); 3355 BUG_ON(!workqueue_freezing);
3354 3356
3355 for_each_possible_cpu(cpu) { 3357 for_each_possible_cpu(cpu) {
3358 struct workqueue_struct *wq;
3356 /* 3359 /*
3357 * nr_active is monotonically decreasing. It's safe 3360 * nr_active is monotonically decreasing. It's safe
3358 * to peek without lock. 3361 * to peek without lock.
@@ -3386,7 +3389,6 @@ out_unlock:
3386 */ 3389 */
3387void thaw_workqueues(void) 3390void thaw_workqueues(void)
3388{ 3391{
3389 struct workqueue_struct *wq;
3390 unsigned int cpu; 3392 unsigned int cpu;
3391 3393
3392 spin_lock(&workqueue_lock); 3394 spin_lock(&workqueue_lock);
@@ -3396,6 +3398,7 @@ void thaw_workqueues(void)
3396 3398
3397 for_each_possible_cpu(cpu) { 3399 for_each_possible_cpu(cpu) {
3398 struct global_cwq *gcwq = get_gcwq(cpu); 3400 struct global_cwq *gcwq = get_gcwq(cpu);
3401 struct workqueue_struct *wq;
3399 3402
3400 spin_lock_irq(&gcwq->lock); 3403 spin_lock_irq(&gcwq->lock);
3401 3404
@@ -3443,7 +3446,7 @@ void __init init_workqueues(void)
3443 * sure cpu number won't overflow into kernel pointer area so 3446 * sure cpu number won't overflow into kernel pointer area so
3444 * that they can be distinguished. 3447 * that they can be distinguished.
3445 */ 3448 */
3446 BUILD_BUG_ON(NR_CPUS << WORK_STRUCT_FLAG_BITS >= PAGE_OFFSET); 3449 BUILD_BUG_ON(WORK_CPU_LAST << WORK_STRUCT_FLAG_BITS >= PAGE_OFFSET);
3447 3450
3448 hotcpu_notifier(workqueue_cpu_callback, CPU_PRI_WORKQUEUE); 3451 hotcpu_notifier(workqueue_cpu_callback, CPU_PRI_WORKQUEUE);
3449 3452