History

workqueue: increase max_active of keventd and kill current_is_keventd()

Define WQ_MAX_ACTIVE and create keventd with max_active set to half of it which means that keventd now can process upto WQ_MAX_ACTIVE / 2 - 1 works concurrently. Unless some combination can result in dependency loop longer than max_active, deadlock won't happen and thus it's unnecessary to check whether current_is_keventd() before trying to schedule a work. Kill current_is_keventd(). (Lockdep annotations are broken. We need lock_map_acquire_read_norecurse())

Tejun Heo committed 16 years ago

Commit b71ab8c1 parent e22bee74 files · +18 −53Browse files

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

Unified · Split

kernel/workqueue.c+13−50
@@ -2398,7 +2398,6 @@ EXPORT_SYMBOL(schedule_delayed_work_on); · 2397 unmodified lines
23982398 int schedule_on_each_cpu(work_func_t func)
23992399 {
24002400 int cpu;
2401− int orig = -1;
24022401 struct work_struct *works;
24032402
24042403 works = alloc_percpu(struct work_struct);
@@ -2407,23 +2406,12 @@ int schedule_on_each_cpu(work_func_t func) · 2 unmodified lines
24072406
24082407 get_online_cpus();
24092408
2410− /*
2411− * When running in keventd don't schedule a work item on
2412− * itself. Can just call directly because the work queue is
2413− * already bound. This also is faster.
2414− */
2415− if (current_is_keventd())
2416− orig = raw_smp_processor_id();
2417−
24182409 for_each_online_cpu(cpu) {
24192410 struct work_struct *work = per_cpu_ptr(works, cpu);
24202411
24212412 INIT_WORK(work, func);
2422− if (cpu != orig)
2423− schedule_work_on(cpu, work);
2413+ schedule_work_on(cpu, work);
24242414 }
2425− if (orig >= 0)
2426− func(per_cpu_ptr(works, orig));
24272415
24282416 for_each_online_cpu(cpu)
24292417 flush_work(per_cpu_ptr(works, cpu));
@@ -2494,41 +2482,6 @@ int keventd_up(void) · 64 unmodified lines
24942482 return keventd_wq != NULL;
24952483 }
24962484
2497−int current_is_keventd(void)
2498−{
2499− bool found = false;
2500− unsigned int cpu;
2501−
2502− /*
2503− * There no longer is one-to-one relation between worker and
2504− * work queue and a worker task might be unbound from its cpu
2505− * if the cpu was offlined. Match all busy workers. This
2506− * function will go away once dynamic pool is implemented.
2507− */
2508− for_each_possible_cpu(cpu) {
2509− struct global_cwq *gcwq = get_gcwq(cpu);
2510− struct worker *worker;
2511− struct hlist_node *pos;
2512− unsigned long flags;
2513− int i;
2514−
2515− spin_lock_irqsave(&gcwq->lock, flags);
2516−
2517− for_each_busy_worker(worker, i, pos, gcwq) {
2518− if (worker->task == current) {
2519− found = true;
2520− break;
2521− }
2522− }
2523−
2524− spin_unlock_irqrestore(&gcwq->lock, flags);
2525− if (found)
2526− break;
2527− }
2528−
2529− return found;
2530−}
2531−
25322485 static struct cpu_workqueue_struct *alloc_cwqs(void)
25332486 {
25342487 /*
@@ -2576,6 +2529,16 @@ static void free_cwqs(struct cpu_workqueue_struct *cwqs) · 41 unmodified lines
25762529 #endif
25772530 }
25782531
2532+static int wq_clamp_max_active(int max_active, const char *name)
2533+{
2534+ if (max_active < 1 || max_active > WQ_MAX_ACTIVE)
2535+ printk(KERN_WARNING "workqueue: max_active %d requested for %s "
2536+ "is out of range, clamping between %d and %d\n",
2537+ max_active, name, 1, WQ_MAX_ACTIVE);
2538+
2539+ return clamp_val(max_active, 1, WQ_MAX_ACTIVE);
2540+}
2541+
25792542 struct workqueue_struct *__create_workqueue_key(const char *name,
25802543 unsigned int flags,
25812544 int max_active,
@@ -2585,7 +2548,7 @@ struct workqueue_struct *__create_workqueue_key(const char *name, · 3 unmodified lines
25852548 struct workqueue_struct *wq;
25862549 unsigned int cpu;
25872550
2588− max_active = clamp_val(max_active, 1, INT_MAX);
2551+ max_active = wq_clamp_max_active(max_active, name);
25892552
25902553 wq = kzalloc(sizeof(*wq), GFP_KERNEL);
25912554 if (!wq)
@@ -3324,6 +3287,6 @@ void __init init_workqueues(void) · 732 unmodified lines
33243287 spin_unlock_irq(&gcwq->lock);
33253288 }
33263289
3327− keventd_wq = create_workqueue("events");
3290+ keventd_wq = __create_workqueue("events", 0, WQ_DFL_ACTIVE);
33283291 BUG_ON(!keventd_wq);
33293292 }