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/workqueue.c (1 of 1 file). Show all

Unified · Split

kernel/workqueue.c+38−29
@@ -3329,6 +3329,23 @@ fail: · 3328 unmodified lines
3329 return NULL;3329 return NULL;
3330}3330}
3331 3331
3332/* initialize @pwq which interfaces with @pool for @wq and link it in */
3333static 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
3332static int alloc_and_link_pwqs(struct workqueue_struct *wq)3349static int alloc_and_link_pwqs(struct workqueue_struct *wq)
3333{3350{
3334 bool highpri = wq->flags & WQ_HIGHPRI;3351 bool highpri = wq->flags & WQ_HIGHPRI;
@@ -3345,23 +3362,23 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq) · 10 unmodified lines
3345 struct worker_pool *cpu_pools =3362 struct worker_pool *cpu_pools =
3346 per_cpu(cpu_worker_pools, cpu);3363 per_cpu(cpu_worker_pools, cpu);
3347 3364
3348 pwq->pool = &cpu_pools[highpri];3365 init_and_link_pwq(pwq, wq, &cpu_pools[highpri]);
3349 list_add_tail_rcu(&pwq->pwqs_node, &wq->pwqs);
3350 }3366 }
3351 } else {3367 } else {
3352 struct pool_workqueue *pwq;3368 struct pool_workqueue *pwq;
3369 struct worker_pool *pool;
3353 3370
3354 pwq = kmem_cache_zalloc(pwq_cache, GFP_KERNEL);3371 pwq = kmem_cache_zalloc(pwq_cache, GFP_KERNEL);
3355 if (!pwq)3372 if (!pwq)
3356 return -ENOMEM;3373 return -ENOMEM;
3357 3374
3358 pwq->pool = get_unbound_pool(unbound_std_wq_attrs[highpri]);3375 pool = get_unbound_pool(unbound_std_wq_attrs[highpri]);
3359 if (!pwq->pool) {3376 if (!pool) {
3360 kmem_cache_free(pwq_cache, pwq);3377 kmem_cache_free(pwq_cache, pwq);
3361 return -ENOMEM;3378 return -ENOMEM;
3362 }3379 }
3363 3380
3364 list_add_tail_rcu(&pwq->pwqs_node, &wq->pwqs);3381 init_and_link_pwq(pwq, wq, pool);
3365 }3382 }
3366 3383
3367 return 0;3384 return 0;
@@ -3406,7 +3423,7 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt, · 38 unmodified lines
3406 3423
3407 wq = kzalloc(sizeof(*wq) + namelen, GFP_KERNEL);3424 wq = kzalloc(sizeof(*wq) + namelen, GFP_KERNEL);
3408 if (!wq)3425 if (!wq)
3409 goto err;3426 return NULL;
3410 3427
3411 vsnprintf(wq->name, namelen, fmt, args1);3428 vsnprintf(wq->name, namelen, fmt, args1);
3412 va_end(args);3429 va_end(args);
@@ -3429,18 +3446,7 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt, · 16 unmodified lines
3429 INIT_LIST_HEAD(&wq->list);3446 INIT_LIST_HEAD(&wq->list);
3430 3447
3431 if (alloc_and_link_pwqs(wq) < 0)3448 if (alloc_and_link_pwqs(wq) < 0)
3432 goto err;3449 goto err_free_wq;
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();
3444 3450
3445 /*3451 /*
3446 * Workqueues which may be used during memory reclaim should3452 * 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
3449 if (flags & WQ_MEM_RECLAIM) {3455 if (flags & WQ_MEM_RECLAIM) {
3450 struct worker *rescuer;3456 struct worker *rescuer;
3451 3457
3452 wq->rescuer = rescuer = alloc_worker();3458 rescuer = alloc_worker();
3453 if (!rescuer)3459 if (!rescuer)
3454 goto err;3460 goto err_destroy;
3455 3461
3456 rescuer->rescue_wq = wq;3462 rescuer->rescue_wq = wq;
3457 rescuer->task = kthread_create(rescuer_thread, rescuer, "%s",3463 rescuer->task = kthread_create(rescuer_thread, rescuer, "%s",
3458 wq->name);3464 wq->name);
3459 if (IS_ERR(rescuer->task))3465 if (IS_ERR(rescuer->task)) {
3460 goto err;3466 kfree(rescuer);
3467 goto err_destroy;
3468 }
3461 3469
3470 wq->rescuer = rescuer;
3462 rescuer->task->flags |= PF_THREAD_BOUND;3471 rescuer->task->flags |= PF_THREAD_BOUND;
3463 wake_up_process(rescuer->task);3472 wake_up_process(rescuer->task);
3464 }3473 }
@@ -3479,12 +3488,12 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt, · 14 unmodified lines
3479 spin_unlock_irq(&workqueue_lock);3488 spin_unlock_irq(&workqueue_lock);
3480 3489
3481 return wq;3490 return wq;
3482err:3491
3483 if (wq) {3492err_free_wq:
3484 free_pwqs(wq);3493 kfree(wq);
3485 kfree(wq->rescuer);3494 return NULL;
3486 kfree(wq);3495err_destroy:
3487 }3496 destroy_workqueue(wq);
3488 return NULL;3497 return NULL;
3489}3498}
3490EXPORT_SYMBOL_GPL(__alloc_workqueue_key);3499EXPORT_SYMBOL_GPL(__alloc_workqueue_key);
@@ -3526,7 +3535,7 @@ void destroy_workqueue(struct workqueue_struct *wq) · 35 unmodified lines
3526 * wq list is used to freeze wq, remove from list after3535 * wq list is used to freeze wq, remove from list after
3527 * flushing is complete in case freeze races us.3536 * flushing is complete in case freeze races us.
3528 */3537 */
3529 list_del(&wq->list);3538 list_del_init(&wq->list);
3530 3539
3531 spin_unlock_irq(&workqueue_lock);3540 spin_unlock_irq(&workqueue_lock);
3532 3541