diff options
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r-- | kernel/workqueue.c | 99 |
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 | ||
127 | DEFINE_TRACE(workqueue_insertion); | ||
128 | |||
128 | static void insert_work(struct cpu_workqueue_struct *cwq, | 129 | static 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 | } |
260 | EXPORT_SYMBOL_GPL(queue_delayed_work_on); | 263 | EXPORT_SYMBOL_GPL(queue_delayed_work_on); |
261 | 264 | ||
265 | DEFINE_TRACE(workqueue_execution); | ||
266 | |||
262 | static void run_workqueue(struct cpu_workqueue_struct *cwq) | 267 | static 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 | ||
369 | static int flush_cpu_workqueue(struct cpu_workqueue_struct *cwq) | 366 | static 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 | } |
422 | EXPORT_SYMBOL_GPL(flush_workqueue); | 410 | EXPORT_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 | ||
756 | DEFINE_TRACE(workqueue_creation); | ||
757 | |||
768 | static int create_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu) | 758 | static 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, ¶m); | 777 | sched_setscheduler_nocheck(p, SCHED_FIFO, ¶m); |
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 | } |
869 | EXPORT_SYMBOL_GPL(__create_workqueue_key); | 861 | EXPORT_SYMBOL_GPL(__create_workqueue_key); |
870 | 862 | ||
863 | DEFINE_TRACE(workqueue_destruction); | ||
864 | |||
871 | static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq) | 865 | static 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 |
974 | static struct workqueue_struct *work_on_cpu_wq __read_mostly; | ||
975 | 969 | ||
976 | struct work_for_cpu { | 970 | struct 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 | ||
983 | static void do_work_for_cpu(struct work_struct *w) | 977 | static 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 | */ |
999 | long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg) | 995 | long 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 | } |
1011 | EXPORT_SYMBOL_GPL(work_on_cpu); | 1012 | EXPORT_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 | } |