diff options
Diffstat (limited to 'kernel/workqueue.c')
| -rw-r--r-- | kernel/workqueue.c | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index c68277c204ab..bce1074bdec1 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
| @@ -534,11 +534,37 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq, | |||
| 534 | 534 | ||
| 535 | debug_work_activate(work); | 535 | debug_work_activate(work); |
| 536 | 536 | ||
| 537 | /* determine gcwq to use */ | 537 | /* |
| 538 | * Determine gcwq to use. SINGLE_CPU is inherently | ||
| 539 | * NON_REENTRANT, so test it first. | ||
| 540 | */ | ||
| 538 | if (!(wq->flags & WQ_SINGLE_CPU)) { | 541 | if (!(wq->flags & WQ_SINGLE_CPU)) { |
| 539 | /* just use the requested cpu for multicpu workqueues */ | 542 | struct global_cwq *last_gcwq; |
| 543 | |||
| 544 | /* | ||
| 545 | * It's multi cpu. If @wq is non-reentrant and @work | ||
| 546 | * was previously on a different cpu, it might still | ||
| 547 | * be running there, in which case the work needs to | ||
| 548 | * be queued on that cpu to guarantee non-reentrance. | ||
| 549 | */ | ||
| 540 | gcwq = get_gcwq(cpu); | 550 | gcwq = get_gcwq(cpu); |
| 541 | spin_lock_irqsave(&gcwq->lock, flags); | 551 | if (wq->flags & WQ_NON_REENTRANT && |
| 552 | (last_gcwq = get_work_gcwq(work)) && last_gcwq != gcwq) { | ||
| 553 | struct worker *worker; | ||
| 554 | |||
| 555 | spin_lock_irqsave(&last_gcwq->lock, flags); | ||
| 556 | |||
| 557 | worker = find_worker_executing_work(last_gcwq, work); | ||
| 558 | |||
| 559 | if (worker && worker->current_cwq->wq == wq) | ||
| 560 | gcwq = last_gcwq; | ||
| 561 | else { | ||
| 562 | /* meh... not running there, queue here */ | ||
| 563 | spin_unlock_irqrestore(&last_gcwq->lock, flags); | ||
| 564 | spin_lock_irqsave(&gcwq->lock, flags); | ||
| 565 | } | ||
| 566 | } else | ||
| 567 | spin_lock_irqsave(&gcwq->lock, flags); | ||
| 542 | } else { | 568 | } else { |
| 543 | unsigned int req_cpu = cpu; | 569 | unsigned int req_cpu = cpu; |
| 544 | 570 | ||
