History

workqueue: implement WQ_NON_REENTRANT

With gcwq managing all the workers and work->data pointing to the last gcwq it was on, non-reentrance can be easily implemented by checking whether the work is still running on the previous gcwq on queueing. Implement it.

Tejun Heo committed 16 years ago

Commit 18aa9ef1 parent 7a22ad72 files · +30 −3Browse files

Showing the changes to kernel/workqueue.c (1 of 2 files). Show all

Unified · Split

kernel/workqueue.c+29−3
@@ -534,11 +534,37 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq, · 533 unmodified lines
534534
535535 debug_work_activate(work);
536536
537− /* determine gcwq to use */
537+ /*
538+ * Determine gcwq to use. SINGLE_CPU is inherently
539+ * NON_REENTRANT, so test it first.
540+ */
538541 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+ */
540550 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);
542568 } else {
543569 unsigned int req_cpu = cpu;
544570

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t