aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/workqueue.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r--kernel/workqueue.c99
1 files changed, 48 insertions, 51 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 1f0c509b40d3..f71fb2a08950 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -33,6 +33,7 @@
33#include <linux/kallsyms.h> 33#include <linux/kallsyms.h>
34#include <linux/debug_locks.h> 34#include <linux/debug_locks.h>
35#include <linux/lockdep.h> 35#include <linux/lockdep.h>
36#include <trace/workqueue.h>
36 37
37/* 38/*
38 * The per-CPU workqueue (if single thread, we always use the first 39 * The per-CPU workqueue (if single thread, we always use the first
@@ -48,8 +49,6 @@ struct cpu_workqueue_struct {
48 49
49 struct workqueue_struct *wq; 50 struct workqueue_struct *wq;
50 struct task_struct *thread; 51 struct task_struct *thread;
51
52 int run_depth; /* Detect run_workqueue() recursion depth */
53} ____cacheline_aligned; 52} ____cacheline_aligned;
54 53
55/* 54/*
@@ -125,9 +124,13 @@ struct cpu_workqueue_struct *get_wq_data(struct work_struct *work)
125 return (void *) (atomic_long_read(&work->data) & WORK_STRUCT_WQ_DATA_MASK); 124 return (void *) (atomic_long_read(&work->data) & WORK_STRUCT_WQ_DATA_MASK);
126} 125}
127 126
127DEFINE_TRACE(workqueue_insertion);
128
128static void insert_work(struct cpu_workqueue_struct *cwq, 129static void insert_work(struct cpu_workqueue_struct *cwq,
129 struct work_struct *work, struct list_head *head) 130 struct work_struct *work, struct list_head *head)
130{ 131{
132 trace_workqueue_insertion(cwq->thread, work);
133
131 set_wq_data(work, cwq); 134 set_wq_data(work, cwq);
132 /* 135 /*
133 * Ensure that we get the right work->data if we see the 136 * Ensure that we get the right work->data if we see the
@@ -259,16 +262,11 @@ int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
259} 262}
260EXPORT_SYMBOL_GPL(queue_delayed_work_on); 263EXPORT_SYMBOL_GPL(queue_delayed_work_on);
261 264
265DEFINE_TRACE(workqueue_execution);
266
262static void run_workqueue(struct cpu_workqueue_struct *cwq) 267static void run_workqueue(struct cpu_workqueue_struct *cwq)
263{ 268{
264 spin_lock_irq(&cwq->lock); 269 spin_lock_irq(&cwq->lock);
265 cwq->run_depth++;
266 if (cwq->run_depth > 3) {
267 /* morton gets to eat his hat */
268 printk("%s: recursion depth exceeded: %d\n",
269 __func__, cwq->run_depth);
270 dump_stack();
271 }
272 while (!list_empty(&cwq->worklist)) { 270 while (!list_empty(&cwq->worklist)) {
273 struct work_struct *work = list_entry(cwq->worklist.next, 271 struct work_struct *work = list_entry(cwq->worklist.next,
274 struct work_struct, entry); 272 struct work_struct, entry);
@@ -284,7 +282,7 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq)
284 */ 282 */
285 struct lockdep_map lockdep_map = work->lockdep_map; 283 struct lockdep_map lockdep_map = work->lockdep_map;
286#endif 284#endif
287 285 trace_workqueue_execution(cwq->thread, work);
288 cwq->current_work = work; 286 cwq->current_work = work;
289 list_del_init(cwq->worklist.next); 287 list_del_init(cwq->worklist.next);
290 spin_unlock_irq(&cwq->lock); 288 spin_unlock_irq(&cwq->lock);
@@ -311,7 +309,6 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq)
311 spin_lock_irq(&cwq->lock); 309 spin_lock_irq(&cwq->lock);
312 cwq->current_work = NULL; 310 cwq->current_work = NULL;
313 } 311 }
314 cwq->run_depth--;
315 spin_unlock_irq(&cwq->lock); 312 spin_unlock_irq(&cwq->lock);
316} 313}
317 314
@@ -368,29 +365,20 @@ static void insert_wq_barrier(struct cpu_workqueue_struct *cwq,
368 365
369static int flush_cpu_workqueue(struct cpu_workqueue_struct *cwq) 366static int flush_cpu_workqueue(struct cpu_workqueue_struct *cwq)
370{ 367{
371 int active; 368 int active = 0;
372 369 struct wq_barrier barr;
373 if (cwq->thread == current) {
374 /*
375 * Probably keventd trying to flush its own queue. So simply run
376 * it by hand rather than deadlocking.
377 */
378 run_workqueue(cwq);
379 active = 1;
380 } else {
381 struct wq_barrier barr;
382 370
383 active = 0; 371 WARN_ON(cwq->thread == current);
384 spin_lock_irq(&cwq->lock);
385 if (!list_empty(&cwq->worklist) || cwq->current_work != NULL) {
386 insert_wq_barrier(cwq, &barr, &cwq->worklist);
387 active = 1;
388 }
389 spin_unlock_irq(&cwq->lock);
390 372
391 if (active) 373 spin_lock_irq(&cwq->lock);
392 wait_for_completion(&barr.done); 374 if (!list_empty(&cwq->worklist) || cwq->current_work != NULL) {
375 insert_wq_barrier(cwq, &barr, &cwq->worklist);
376 active = 1;
393 } 377 }
378 spin_unlock_irq(&cwq->lock);
379
380 if (active)
381 wait_for_completion(&barr.done);
394 382
395 return active; 383 return active;
396} 384}
@@ -416,7 +404,7 @@ void flush_workqueue(struct workqueue_struct *wq)
416 might_sleep(); 404 might_sleep();
417 lock_map_acquire(&wq->lockdep_map); 405 lock_map_acquire(&wq->lockdep_map);
418 lock_map_release(&wq->lockdep_map); 406 lock_map_release(&wq->lockdep_map);
419 for_each_cpu_mask_nr(cpu, *cpu_map) 407 for_each_cpu(cpu, cpu_map)
420 flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, cpu)); 408 flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, cpu));
421} 409}
422EXPORT_SYMBOL_GPL(flush_workqueue); 410EXPORT_SYMBOL_GPL(flush_workqueue);
@@ -547,7 +535,7 @@ static void wait_on_work(struct work_struct *work)
547 wq = cwq->wq; 535 wq = cwq->wq;
548 cpu_map = wq_cpu_map(wq); 536 cpu_map = wq_cpu_map(wq);
549 537
550 for_each_cpu_mask_nr(cpu, *cpu_map) 538 for_each_cpu(cpu, cpu_map)
551 wait_on_cpu_work(per_cpu_ptr(wq->cpu_wq, cpu), work); 539 wait_on_cpu_work(per_cpu_ptr(wq->cpu_wq, cpu), work);
552} 540}
553 541
@@ -765,6 +753,8 @@ init_cpu_workqueue(struct workqueue_struct *wq, int cpu)
765 return cwq; 753 return cwq;
766} 754}
767 755
756DEFINE_TRACE(workqueue_creation);
757
768static int create_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu) 758static int create_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu)
769{ 759{
770 struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 }; 760 struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
@@ -787,6 +777,8 @@ static int create_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu)
787 sched_setscheduler_nocheck(p, SCHED_FIFO, &param); 777 sched_setscheduler_nocheck(p, SCHED_FIFO, &param);
788 cwq->thread = p; 778 cwq->thread = p;
789 779
780 trace_workqueue_creation(cwq->thread, cpu);
781
790 return 0; 782 return 0;
791} 783}
792 784
@@ -868,6 +860,8 @@ struct workqueue_struct *__create_workqueue_key(const char *name,
868} 860}
869EXPORT_SYMBOL_GPL(__create_workqueue_key); 861EXPORT_SYMBOL_GPL(__create_workqueue_key);
870 862
863DEFINE_TRACE(workqueue_destruction);
864
871static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq) 865static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq)
872{ 866{
873 /* 867 /*
@@ -891,6 +885,7 @@ static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq)
891 * checks list_empty(), and a "normal" queue_work() can't use 885 * checks list_empty(), and a "normal" queue_work() can't use
892 * a dead CPU. 886 * a dead CPU.
893 */ 887 */
888 trace_workqueue_destruction(cwq->thread);
894 kthread_stop(cwq->thread); 889 kthread_stop(cwq->thread);
895 cwq->thread = NULL; 890 cwq->thread = NULL;
896} 891}
@@ -911,7 +906,7 @@ void destroy_workqueue(struct workqueue_struct *wq)
911 list_del(&wq->list); 906 list_del(&wq->list);
912 spin_unlock(&workqueue_lock); 907 spin_unlock(&workqueue_lock);
913 908
914 for_each_cpu_mask_nr(cpu, *cpu_map) 909 for_each_cpu(cpu, cpu_map)
915 cleanup_workqueue_thread(per_cpu_ptr(wq->cpu_wq, cpu)); 910 cleanup_workqueue_thread(per_cpu_ptr(wq->cpu_wq, cpu));
916 cpu_maps_update_done(); 911 cpu_maps_update_done();
917 912
@@ -971,20 +966,20 @@ undo:
971} 966}
972 967
973#ifdef CONFIG_SMP 968#ifdef CONFIG_SMP
974static struct workqueue_struct *work_on_cpu_wq __read_mostly;
975 969
976struct work_for_cpu { 970struct work_for_cpu {
977 struct work_struct work; 971 struct completion completion;
978 long (*fn)(void *); 972 long (*fn)(void *);
979 void *arg; 973 void *arg;
980 long ret; 974 long ret;
981}; 975};
982 976
983static void do_work_for_cpu(struct work_struct *w) 977static int do_work_for_cpu(void *_wfc)
984{ 978{
985 struct work_for_cpu *wfc = container_of(w, struct work_for_cpu, work); 979 struct work_for_cpu *wfc = _wfc;
986
987 wfc->ret = wfc->fn(wfc->arg); 980 wfc->ret = wfc->fn(wfc->arg);
981 complete(&wfc->completion);
982 return 0;
988} 983}
989 984
990/** 985/**
@@ -995,17 +990,23 @@ static void do_work_for_cpu(struct work_struct *w)
995 * 990 *
996 * This will return the value @fn returns. 991 * This will return the value @fn returns.
997 * It is up to the caller to ensure that the cpu doesn't go offline. 992 * It is up to the caller to ensure that the cpu doesn't go offline.
993 * The caller must not hold any locks which would prevent @fn from completing.
998 */ 994 */
999long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg) 995long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg)
1000{ 996{
1001 struct work_for_cpu wfc; 997 struct task_struct *sub_thread;
1002 998 struct work_for_cpu wfc = {
1003 INIT_WORK(&wfc.work, do_work_for_cpu); 999 .completion = COMPLETION_INITIALIZER_ONSTACK(wfc.completion),
1004 wfc.fn = fn; 1000 .fn = fn,
1005 wfc.arg = arg; 1001 .arg = arg,
1006 queue_work_on(cpu, work_on_cpu_wq, &wfc.work); 1002 };
1007 flush_work(&wfc.work); 1003
1008 1004 sub_thread = kthread_create(do_work_for_cpu, &wfc, "work_for_cpu");
1005 if (IS_ERR(sub_thread))
1006 return PTR_ERR(sub_thread);
1007 kthread_bind(sub_thread, cpu);
1008 wake_up_process(sub_thread);
1009 wait_for_completion(&wfc.completion);
1009 return wfc.ret; 1010 return wfc.ret;
1010} 1011}
1011EXPORT_SYMBOL_GPL(work_on_cpu); 1012EXPORT_SYMBOL_GPL(work_on_cpu);
@@ -1021,8 +1022,4 @@ void __init init_workqueues(void)
1021 hotcpu_notifier(workqueue_cpu_callback, 0); 1022 hotcpu_notifier(workqueue_cpu_callback, 0);
1022 keventd_wq = create_workqueue("events"); 1023 keventd_wq = create_workqueue("events");
1023 BUG_ON(!keventd_wq); 1024 BUG_ON(!keventd_wq);
1024#ifdef CONFIG_SMP
1025 work_on_cpu_wq = create_workqueue("work_on_cpu");
1026 BUG_ON(!work_on_cpu_wq);
1027#endif
1028} 1025}