diff options
| author | Ben Collins <bcollins@debian.org> | 2005-11-28 16:43:56 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-28 17:42:23 -0500 |
| commit | bce61dd49d6ba7799be2de17c772e4c701558f14 (patch) | |
| tree | a8fd75afc85ffef3c9af0bafa1989d7a14e1a187 /kernel | |
| parent | ee500f274914653a7d3dfca7d0140a3d21658e32 (diff) | |
[PATCH] Fix hardcoded cpu=0 in workqueue for per_cpu_ptr() calls
Tracked this down on an Ultra Enterprise 3000. It's a 6-way machine. Odd
thing about this machine (and it's good for finding bugs like this) is that
the CPU id's are not 0 based. For instance, on my machine the CPU's are
6/7/10/11/14/15.
This caused some NULL pointer dereference in kernel/workqueue.c because for
single_threaded workqueue's, it hardcoded the cpu to 0.
I changed the 0's to any_online_cpu(cpu_online_mask), which cpumask.h
claims is "First cpu in mask". So this fits the same usage.
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/workqueue.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 42df83d7fad2..2bd5aee1c736 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
| @@ -102,7 +102,7 @@ int fastcall queue_work(struct workqueue_struct *wq, struct work_struct *work) | |||
| 102 | 102 | ||
| 103 | if (!test_and_set_bit(0, &work->pending)) { | 103 | if (!test_and_set_bit(0, &work->pending)) { |
| 104 | if (unlikely(is_single_threaded(wq))) | 104 | if (unlikely(is_single_threaded(wq))) |
| 105 | cpu = 0; | 105 | cpu = any_online_cpu(cpu_online_map); |
| 106 | BUG_ON(!list_empty(&work->entry)); | 106 | BUG_ON(!list_empty(&work->entry)); |
| 107 | __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work); | 107 | __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work); |
| 108 | ret = 1; | 108 | ret = 1; |
| @@ -118,7 +118,7 @@ static void delayed_work_timer_fn(unsigned long __data) | |||
| 118 | int cpu = smp_processor_id(); | 118 | int cpu = smp_processor_id(); |
| 119 | 119 | ||
| 120 | if (unlikely(is_single_threaded(wq))) | 120 | if (unlikely(is_single_threaded(wq))) |
| 121 | cpu = 0; | 121 | cpu = any_online_cpu(cpu_online_map); |
| 122 | 122 | ||
| 123 | __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work); | 123 | __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work); |
| 124 | } | 124 | } |
| @@ -266,8 +266,8 @@ void fastcall flush_workqueue(struct workqueue_struct *wq) | |||
| 266 | might_sleep(); | 266 | might_sleep(); |
| 267 | 267 | ||
| 268 | if (is_single_threaded(wq)) { | 268 | if (is_single_threaded(wq)) { |
| 269 | /* Always use cpu 0's area. */ | 269 | /* Always use first cpu's area. */ |
| 270 | flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, 0)); | 270 | flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, any_online_cpu(cpu_online_map))); |
| 271 | } else { | 271 | } else { |
| 272 | int cpu; | 272 | int cpu; |
| 273 | 273 | ||
| @@ -320,7 +320,7 @@ struct workqueue_struct *__create_workqueue(const char *name, | |||
| 320 | lock_cpu_hotplug(); | 320 | lock_cpu_hotplug(); |
| 321 | if (singlethread) { | 321 | if (singlethread) { |
| 322 | INIT_LIST_HEAD(&wq->list); | 322 | INIT_LIST_HEAD(&wq->list); |
| 323 | p = create_workqueue_thread(wq, 0); | 323 | p = create_workqueue_thread(wq, any_online_cpu(cpu_online_map)); |
| 324 | if (!p) | 324 | if (!p) |
| 325 | destroy = 1; | 325 | destroy = 1; |
| 326 | else | 326 | else |
| @@ -374,7 +374,7 @@ void destroy_workqueue(struct workqueue_struct *wq) | |||
| 374 | /* We don't need the distraction of CPUs appearing and vanishing. */ | 374 | /* We don't need the distraction of CPUs appearing and vanishing. */ |
| 375 | lock_cpu_hotplug(); | 375 | lock_cpu_hotplug(); |
| 376 | if (is_single_threaded(wq)) | 376 | if (is_single_threaded(wq)) |
| 377 | cleanup_workqueue_thread(wq, 0); | 377 | cleanup_workqueue_thread(wq, any_online_cpu(cpu_online_map)); |
| 378 | else { | 378 | else { |
| 379 | for_each_online_cpu(cpu) | 379 | for_each_online_cpu(cpu) |
| 380 | cleanup_workqueue_thread(wq, cpu); | 380 | cleanup_workqueue_thread(wq, cpu); |
