diff options
| author | Dave Jones <davej@redhat.com> | 2006-09-05 17:20:21 -0400 |
|---|---|---|
| committer | Dave Jones <davej@redhat.com> | 2006-09-05 17:20:21 -0400 |
| commit | 115b384cf87249d76adb0b21aca11ee22128927d (patch) | |
| tree | f39a2a54863e9d82d1196906f92c82ab5991c6af /kernel/workqueue.c | |
| parent | 8eb7925f93af75e66a240d148efdec212f95bcb7 (diff) | |
| parent | c336923b668fdcf0312efbec3b44895d713f4d81 (diff) | |
Merge ../linus
Diffstat (limited to 'kernel/workqueue.c')
| -rw-r--r-- | kernel/workqueue.c | 91 |
1 files changed, 75 insertions, 16 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index eebb1d839235..835fe28b87a8 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
| @@ -68,7 +68,7 @@ struct workqueue_struct { | |||
| 68 | 68 | ||
| 69 | /* All the per-cpu workqueues on the system, for hotplug cpu to add/remove | 69 | /* All the per-cpu workqueues on the system, for hotplug cpu to add/remove |
| 70 | threads to each one as cpus come/go. */ | 70 | threads to each one as cpus come/go. */ |
| 71 | static DEFINE_SPINLOCK(workqueue_lock); | 71 | static DEFINE_MUTEX(workqueue_mutex); |
| 72 | static LIST_HEAD(workqueues); | 72 | static LIST_HEAD(workqueues); |
| 73 | 73 | ||
| 74 | static int singlethread_cpu; | 74 | static int singlethread_cpu; |
| @@ -93,9 +93,12 @@ static void __queue_work(struct cpu_workqueue_struct *cwq, | |||
| 93 | spin_unlock_irqrestore(&cwq->lock, flags); | 93 | spin_unlock_irqrestore(&cwq->lock, flags); |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | /* | 96 | /** |
| 97 | * Queue work on a workqueue. Return non-zero if it was successfully | 97 | * queue_work - queue work on a workqueue |
| 98 | * added. | 98 | * @wq: workqueue to use |
| 99 | * @work: work to queue | ||
| 100 | * | ||
| 101 | * Returns non-zero if it was successfully added. | ||
| 99 | * | 102 | * |
| 100 | * We queue the work to the CPU it was submitted, but there is no | 103 | * We queue the work to the CPU it was submitted, but there is no |
| 101 | * guarantee that it will be processed by that CPU. | 104 | * guarantee that it will be processed by that CPU. |
| @@ -128,6 +131,14 @@ static void delayed_work_timer_fn(unsigned long __data) | |||
| 128 | __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work); | 131 | __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work); |
| 129 | } | 132 | } |
| 130 | 133 | ||
| 134 | /** | ||
| 135 | * queue_delayed_work - queue work on a workqueue after delay | ||
| 136 | * @wq: workqueue to use | ||
| 137 | * @work: work to queue | ||
| 138 | * @delay: number of jiffies to wait before queueing | ||
| 139 | * | ||
| 140 | * Returns non-zero if it was successfully added. | ||
| 141 | */ | ||
| 131 | int fastcall queue_delayed_work(struct workqueue_struct *wq, | 142 | int fastcall queue_delayed_work(struct workqueue_struct *wq, |
| 132 | struct work_struct *work, unsigned long delay) | 143 | struct work_struct *work, unsigned long delay) |
| 133 | { | 144 | { |
| @@ -150,6 +161,15 @@ int fastcall queue_delayed_work(struct workqueue_struct *wq, | |||
| 150 | } | 161 | } |
| 151 | EXPORT_SYMBOL_GPL(queue_delayed_work); | 162 | EXPORT_SYMBOL_GPL(queue_delayed_work); |
| 152 | 163 | ||
| 164 | /** | ||
| 165 | * queue_delayed_work_on - queue work on specific CPU after delay | ||
| 166 | * @cpu: CPU number to execute work on | ||
| 167 | * @wq: workqueue to use | ||
| 168 | * @work: work to queue | ||
| 169 | * @delay: number of jiffies to wait before queueing | ||
| 170 | * | ||
| 171 | * Returns non-zero if it was successfully added. | ||
| 172 | */ | ||
| 153 | int queue_delayed_work_on(int cpu, struct workqueue_struct *wq, | 173 | int queue_delayed_work_on(int cpu, struct workqueue_struct *wq, |
| 154 | struct work_struct *work, unsigned long delay) | 174 | struct work_struct *work, unsigned long delay) |
| 155 | { | 175 | { |
| @@ -275,8 +295,9 @@ static void flush_cpu_workqueue(struct cpu_workqueue_struct *cwq) | |||
| 275 | } | 295 | } |
| 276 | } | 296 | } |
| 277 | 297 | ||
| 278 | /* | 298 | /** |
| 279 | * flush_workqueue - ensure that any scheduled work has run to completion. | 299 | * flush_workqueue - ensure that any scheduled work has run to completion. |
| 300 | * @wq: workqueue to flush | ||
| 280 | * | 301 | * |
| 281 | * Forces execution of the workqueue and blocks until its completion. | 302 | * Forces execution of the workqueue and blocks until its completion. |
| 282 | * This is typically used in driver shutdown handlers. | 303 | * This is typically used in driver shutdown handlers. |
| @@ -299,10 +320,10 @@ void fastcall flush_workqueue(struct workqueue_struct *wq) | |||
| 299 | } else { | 320 | } else { |
| 300 | int cpu; | 321 | int cpu; |
| 301 | 322 | ||
| 302 | lock_cpu_hotplug(); | 323 | mutex_lock(&workqueue_mutex); |
| 303 | for_each_online_cpu(cpu) | 324 | for_each_online_cpu(cpu) |
| 304 | flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, cpu)); | 325 | flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, cpu)); |
| 305 | unlock_cpu_hotplug(); | 326 | mutex_unlock(&workqueue_mutex); |
| 306 | } | 327 | } |
| 307 | } | 328 | } |
| 308 | EXPORT_SYMBOL_GPL(flush_workqueue); | 329 | EXPORT_SYMBOL_GPL(flush_workqueue); |
| @@ -350,8 +371,7 @@ struct workqueue_struct *__create_workqueue(const char *name, | |||
| 350 | } | 371 | } |
| 351 | 372 | ||
| 352 | wq->name = name; | 373 | wq->name = name; |
| 353 | /* We don't need the distraction of CPUs appearing and vanishing. */ | 374 | mutex_lock(&workqueue_mutex); |
| 354 | lock_cpu_hotplug(); | ||
| 355 | if (singlethread) { | 375 | if (singlethread) { |
| 356 | INIT_LIST_HEAD(&wq->list); | 376 | INIT_LIST_HEAD(&wq->list); |
| 357 | p = create_workqueue_thread(wq, singlethread_cpu); | 377 | p = create_workqueue_thread(wq, singlethread_cpu); |
| @@ -360,9 +380,7 @@ struct workqueue_struct *__create_workqueue(const char *name, | |||
| 360 | else | 380 | else |
| 361 | wake_up_process(p); | 381 | wake_up_process(p); |
| 362 | } else { | 382 | } else { |
| 363 | spin_lock(&workqueue_lock); | ||
| 364 | list_add(&wq->list, &workqueues); | 383 | list_add(&wq->list, &workqueues); |
| 365 | spin_unlock(&workqueue_lock); | ||
| 366 | for_each_online_cpu(cpu) { | 384 | for_each_online_cpu(cpu) { |
| 367 | p = create_workqueue_thread(wq, cpu); | 385 | p = create_workqueue_thread(wq, cpu); |
| 368 | if (p) { | 386 | if (p) { |
| @@ -372,7 +390,7 @@ struct workqueue_struct *__create_workqueue(const char *name, | |||
| 372 | destroy = 1; | 390 | destroy = 1; |
| 373 | } | 391 | } |
| 374 | } | 392 | } |
| 375 | unlock_cpu_hotplug(); | 393 | mutex_unlock(&workqueue_mutex); |
| 376 | 394 | ||
| 377 | /* | 395 | /* |
| 378 | * Was there any error during startup? If yes then clean up: | 396 | * Was there any error during startup? If yes then clean up: |
| @@ -400,6 +418,12 @@ static void cleanup_workqueue_thread(struct workqueue_struct *wq, int cpu) | |||
| 400 | kthread_stop(p); | 418 | kthread_stop(p); |
| 401 | } | 419 | } |
| 402 | 420 | ||
| 421 | /** | ||
| 422 | * destroy_workqueue - safely terminate a workqueue | ||
| 423 | * @wq: target workqueue | ||
| 424 | * | ||
| 425 | * Safely destroy a workqueue. All work currently pending will be done first. | ||
| 426 | */ | ||
| 403 | void destroy_workqueue(struct workqueue_struct *wq) | 427 | void destroy_workqueue(struct workqueue_struct *wq) |
| 404 | { | 428 | { |
| 405 | int cpu; | 429 | int cpu; |
| @@ -407,17 +431,15 @@ void destroy_workqueue(struct workqueue_struct *wq) | |||
| 407 | flush_workqueue(wq); | 431 | flush_workqueue(wq); |
| 408 | 432 | ||
| 409 | /* We don't need the distraction of CPUs appearing and vanishing. */ | 433 | /* We don't need the distraction of CPUs appearing and vanishing. */ |
| 410 | lock_cpu_hotplug(); | 434 | mutex_lock(&workqueue_mutex); |
| 411 | if (is_single_threaded(wq)) | 435 | if (is_single_threaded(wq)) |
| 412 | cleanup_workqueue_thread(wq, singlethread_cpu); | 436 | cleanup_workqueue_thread(wq, singlethread_cpu); |
| 413 | else { | 437 | else { |
| 414 | for_each_online_cpu(cpu) | 438 | for_each_online_cpu(cpu) |
| 415 | cleanup_workqueue_thread(wq, cpu); | 439 | cleanup_workqueue_thread(wq, cpu); |
| 416 | spin_lock(&workqueue_lock); | ||
| 417 | list_del(&wq->list); | 440 | list_del(&wq->list); |
| 418 | spin_unlock(&workqueue_lock); | ||
| 419 | } | 441 | } |
| 420 | unlock_cpu_hotplug(); | 442 | mutex_unlock(&workqueue_mutex); |
| 421 | free_percpu(wq->cpu_wq); | 443 | free_percpu(wq->cpu_wq); |
| 422 | kfree(wq); | 444 | kfree(wq); |
| 423 | } | 445 | } |
| @@ -425,18 +447,41 @@ EXPORT_SYMBOL_GPL(destroy_workqueue); | |||
| 425 | 447 | ||
| 426 | static struct workqueue_struct *keventd_wq; | 448 | static struct workqueue_struct *keventd_wq; |
| 427 | 449 | ||
| 450 | /** | ||
| 451 | * schedule_work - put work task in global workqueue | ||
| 452 | * @work: job to be done | ||
| 453 | * | ||
| 454 | * This puts a job in the kernel-global workqueue. | ||
| 455 | */ | ||
| 428 | int fastcall schedule_work(struct work_struct *work) | 456 | int fastcall schedule_work(struct work_struct *work) |
| 429 | { | 457 | { |
| 430 | return queue_work(keventd_wq, work); | 458 | return queue_work(keventd_wq, work); |
| 431 | } | 459 | } |
| 432 | EXPORT_SYMBOL(schedule_work); | 460 | EXPORT_SYMBOL(schedule_work); |
| 433 | 461 | ||
| 462 | /** | ||
| 463 | * schedule_delayed_work - put work task in global workqueue after delay | ||
| 464 | * @work: job to be done | ||
| 465 | * @delay: number of jiffies to wait | ||
| 466 | * | ||
| 467 | * After waiting for a given time this puts a job in the kernel-global | ||
| 468 | * workqueue. | ||
| 469 | */ | ||
| 434 | int fastcall schedule_delayed_work(struct work_struct *work, unsigned long delay) | 470 | int fastcall schedule_delayed_work(struct work_struct *work, unsigned long delay) |
| 435 | { | 471 | { |
| 436 | return queue_delayed_work(keventd_wq, work, delay); | 472 | return queue_delayed_work(keventd_wq, work, delay); |
| 437 | } | 473 | } |
| 438 | EXPORT_SYMBOL(schedule_delayed_work); | 474 | EXPORT_SYMBOL(schedule_delayed_work); |
| 439 | 475 | ||
| 476 | /** | ||
| 477 | * schedule_delayed_work_on - queue work in global workqueue on CPU after delay | ||
| 478 | * @cpu: cpu to use | ||
| 479 | * @work: job to be done | ||
| 480 | * @delay: number of jiffies to wait | ||
| 481 | * | ||
| 482 | * After waiting for a given time this puts a job in the kernel-global | ||
| 483 | * workqueue on the specified CPU. | ||
| 484 | */ | ||
| 440 | int schedule_delayed_work_on(int cpu, | 485 | int schedule_delayed_work_on(int cpu, |
| 441 | struct work_struct *work, unsigned long delay) | 486 | struct work_struct *work, unsigned long delay) |
| 442 | { | 487 | { |
| @@ -465,11 +510,13 @@ int schedule_on_each_cpu(void (*func)(void *info), void *info) | |||
| 465 | if (!works) | 510 | if (!works) |
| 466 | return -ENOMEM; | 511 | return -ENOMEM; |
| 467 | 512 | ||
| 513 | mutex_lock(&workqueue_mutex); | ||
| 468 | for_each_online_cpu(cpu) { | 514 | for_each_online_cpu(cpu) { |
| 469 | INIT_WORK(per_cpu_ptr(works, cpu), func, info); | 515 | INIT_WORK(per_cpu_ptr(works, cpu), func, info); |
| 470 | __queue_work(per_cpu_ptr(keventd_wq->cpu_wq, cpu), | 516 | __queue_work(per_cpu_ptr(keventd_wq->cpu_wq, cpu), |
| 471 | per_cpu_ptr(works, cpu)); | 517 | per_cpu_ptr(works, cpu)); |
| 472 | } | 518 | } |
| 519 | mutex_unlock(&workqueue_mutex); | ||
| 473 | flush_workqueue(keventd_wq); | 520 | flush_workqueue(keventd_wq); |
| 474 | free_percpu(works); | 521 | free_percpu(works); |
| 475 | return 0; | 522 | return 0; |
| @@ -585,6 +632,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, | |||
| 585 | 632 | ||
| 586 | switch (action) { | 633 | switch (action) { |
| 587 | case CPU_UP_PREPARE: | 634 | case CPU_UP_PREPARE: |
| 635 | mutex_lock(&workqueue_mutex); | ||
| 588 | /* Create a new workqueue thread for it. */ | 636 | /* Create a new workqueue thread for it. */ |
| 589 | list_for_each_entry(wq, &workqueues, list) { | 637 | list_for_each_entry(wq, &workqueues, list) { |
| 590 | if (!create_workqueue_thread(wq, hotcpu)) { | 638 | if (!create_workqueue_thread(wq, hotcpu)) { |
| @@ -603,6 +651,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, | |||
| 603 | kthread_bind(cwq->thread, hotcpu); | 651 | kthread_bind(cwq->thread, hotcpu); |
| 604 | wake_up_process(cwq->thread); | 652 | wake_up_process(cwq->thread); |
| 605 | } | 653 | } |
| 654 | mutex_unlock(&workqueue_mutex); | ||
| 606 | break; | 655 | break; |
| 607 | 656 | ||
| 608 | case CPU_UP_CANCELED: | 657 | case CPU_UP_CANCELED: |
| @@ -614,6 +663,15 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, | |||
| 614 | any_online_cpu(cpu_online_map)); | 663 | any_online_cpu(cpu_online_map)); |
| 615 | cleanup_workqueue_thread(wq, hotcpu); | 664 | cleanup_workqueue_thread(wq, hotcpu); |
| 616 | } | 665 | } |
| 666 | mutex_unlock(&workqueue_mutex); | ||
| 667 | break; | ||
| 668 | |||
| 669 | case CPU_DOWN_PREPARE: | ||
| 670 | mutex_lock(&workqueue_mutex); | ||
| 671 | break; | ||
| 672 | |||
| 673 | case CPU_DOWN_FAILED: | ||
| 674 | mutex_unlock(&workqueue_mutex); | ||
| 617 | break; | 675 | break; |
| 618 | 676 | ||
| 619 | case CPU_DEAD: | 677 | case CPU_DEAD: |
| @@ -621,6 +679,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, | |||
| 621 | cleanup_workqueue_thread(wq, hotcpu); | 679 | cleanup_workqueue_thread(wq, hotcpu); |
| 622 | list_for_each_entry(wq, &workqueues, list) | 680 | list_for_each_entry(wq, &workqueues, list) |
| 623 | take_over_work(wq, hotcpu); | 681 | take_over_work(wq, hotcpu); |
| 682 | mutex_unlock(&workqueue_mutex); | ||
| 624 | break; | 683 | break; |
| 625 | } | 684 | } |
| 626 | 685 | ||
