History

workqueue: restructure __alloc_workqueue_key()

* Move initialization and linking of pool_workqueues into init_and_link_pwq(). * Make the failure path use destroy_workqueue() once pool_workqueue initialization succeeds. These changes are to prepare for dynamic management of pool_workqueues and don't introduce any functional changes. While at it, convert list_del(&wq->list) to list_del_init() as a precaution as scheduled changes will make destruction more complex.

Tejun Heo committed 13 years ago

Commit d2c1d401 parent 493008a1 file · +38 −29Browse files

Showing the changes to kernel (1 of 1 file). Show all

Unified · Split

kernel/workqueue.c+38−29
@@ -3329,6 +3329,23 @@ fail: · 3328 unmodified lines
33293329 return NULL;
33303330 }
33313331
3332+/* initialize @pwq which interfaces with @pool for @wq and link it in */
3333+static void init_and_link_pwq(struct pool_workqueue *pwq,
3334+ struct workqueue_struct *wq,
3335+ struct worker_pool *pool)
3336+{
3337+ BUG_ON((unsigned long)pwq & WORK_STRUCT_FLAG_MASK);
3338+
3339+ pwq->pool = pool;
3340+ pwq->wq = wq;
3341+ pwq->flush_color = -1;
3342+ pwq->max_active = wq->saved_max_active;
3343+ INIT_LIST_HEAD(&pwq->delayed_works);
3344+ INIT_LIST_HEAD(&pwq->mayday_node);
3345+
3346+ list_add_tail_rcu(&pwq->pwqs_node, &wq->pwqs);
3347+}
3348+
33323349 static int alloc_and_link_pwqs(struct workqueue_struct *wq)
33333350 {
33343351 bool highpri = wq->flags & WQ_HIGHPRI;
@@ -3345,23 +3362,23 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq) · 10 unmodified lines
33453362 struct worker_pool *cpu_pools =
33463363 per_cpu(cpu_worker_pools, cpu);
33473364
3348− pwq->pool = &cpu_pools[highpri];
3349− list_add_tail_rcu(&pwq->pwqs_node, &wq->pwqs);
3365+ init_and_link_pwq(pwq, wq, &cpu_pools[highpri]);
33503366 }
33513367 } else {
33523368 struct pool_workqueue *pwq;
3369+ struct worker_pool *pool;
33533370
33543371 pwq = kmem_cache_zalloc(pwq_cache, GFP_KERNEL);
33553372 if (!pwq)
33563373 return -ENOMEM;
33573374
3358− pwq->pool = get_unbound_pool(unbound_std_wq_attrs[highpri]);
3359− if (!pwq->pool) {
3375+ pool = get_unbound_pool(unbound_std_wq_attrs[highpri]);
3376+ if (!pool) {
33603377 kmem_cache_free(pwq_cache, pwq);
33613378 return -ENOMEM;
33623379 }
33633380
3364− list_add_tail_rcu(&pwq->pwqs_node, &wq->pwqs);
3381+ init_and_link_pwq(pwq, wq, pool);
33653382 }
33663383
33673384 return 0;
@@ -3406,7 +3423,7 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt, · 38 unmodified lines
34063423
34073424 wq = kzalloc(sizeof(*wq) + namelen, GFP_KERNEL);
34083425 if (!wq)
3409− goto err;
3426+ return NULL;
34103427
34113428 vsnprintf(wq->name, namelen, fmt, args1);
34123429 va_end(args);
@@ -3429,18 +3446,7 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt, · 16 unmodified lines
34293446 INIT_LIST_HEAD(&wq->list);
34303447
34313448 if (alloc_and_link_pwqs(wq) < 0)
3432− goto err;
3433−
3434− local_irq_disable();
3435− for_each_pwq(pwq, wq) {
3436− BUG_ON((unsigned long)pwq & WORK_STRUCT_FLAG_MASK);
3437− pwq->wq = wq;
3438− pwq->flush_color = -1;
3439− pwq->max_active = max_active;
3440− INIT_LIST_HEAD(&pwq->delayed_works);
3441− INIT_LIST_HEAD(&pwq->mayday_node);
3442− }
3443− local_irq_enable();
3449+ goto err_free_wq;
34443450
34453451 /*
34463452 * Workqueues which may be used during memory reclaim should
@@ -3449,16 +3455,19 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt, · 2 unmodified lines
34493455 if (flags & WQ_MEM_RECLAIM) {
34503456 struct worker *rescuer;
34513457
3452− wq->rescuer = rescuer = alloc_worker();
3458+ rescuer = alloc_worker();
34533459 if (!rescuer)
3454− goto err;
3460+ goto err_destroy;
34553461
34563462 rescuer->rescue_wq = wq;
34573463 rescuer->task = kthread_create(rescuer_thread, rescuer, "%s",
34583464 wq->name);
3459− if (IS_ERR(rescuer->task))
3460− goto err;
3465+ if (IS_ERR(rescuer->task)) {
3466+ kfree(rescuer);
3467+ goto err_destroy;
3468+ }
34613469
3470+ wq->rescuer = rescuer;
34623471 rescuer->task->flags |= PF_THREAD_BOUND;
34633472 wake_up_process(rescuer->task);
34643473 }
@@ -3479,12 +3488,12 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt, · 14 unmodified lines
34793488 spin_unlock_irq(&workqueue_lock);
34803489
34813490 return wq;
3482−err:
3483− if (wq) {
3484− free_pwqs(wq);
3485− kfree(wq->rescuer);
3486− kfree(wq);
3487− }
3491+
3492+err_free_wq:
3493+ kfree(wq);
3494+ return NULL;
3495+err_destroy:
3496+ destroy_workqueue(wq);
34883497 return NULL;
34893498 }
34903499 EXPORT_SYMBOL_GPL(__alloc_workqueue_key);
@@ -3526,7 +3535,7 @@ void destroy_workqueue(struct workqueue_struct *wq) · 35 unmodified lines
35263535 * wq list is used to freeze wq, remove from list after
35273536 * flushing is complete in case freeze races us.
35283537 */
3529− list_del(&wq->list);
3538+ list_del_init(&wq->list);
35303539
35313540 spin_unlock_irq(&workqueue_lock);
35323541