mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-21 06:01:23 +00:00
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. Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Lai Jiangshan <laijs@cn.fujitsu.com>
This commit is contained in:
parent
493008a8e4
commit
d2c1d40487
1 changed files with 38 additions and 29 deletions
|
@ -3329,6 +3329,23 @@ fail:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* initialize @pwq which interfaces with @pool for @wq and link it in */
|
||||||
|
static void init_and_link_pwq(struct pool_workqueue *pwq,
|
||||||
|
struct workqueue_struct *wq,
|
||||||
|
struct worker_pool *pool)
|
||||||
|
{
|
||||||
|
BUG_ON((unsigned long)pwq & WORK_STRUCT_FLAG_MASK);
|
||||||
|
|
||||||
|
pwq->pool = pool;
|
||||||
|
pwq->wq = wq;
|
||||||
|
pwq->flush_color = -1;
|
||||||
|
pwq->max_active = wq->saved_max_active;
|
||||||
|
INIT_LIST_HEAD(&pwq->delayed_works);
|
||||||
|
INIT_LIST_HEAD(&pwq->mayday_node);
|
||||||
|
|
||||||
|
list_add_tail_rcu(&pwq->pwqs_node, &wq->pwqs);
|
||||||
|
}
|
||||||
|
|
||||||
static int alloc_and_link_pwqs(struct workqueue_struct *wq)
|
static int alloc_and_link_pwqs(struct workqueue_struct *wq)
|
||||||
{
|
{
|
||||||
bool highpri = wq->flags & WQ_HIGHPRI;
|
bool highpri = wq->flags & WQ_HIGHPRI;
|
||||||
|
@ -3345,23 +3362,23 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq)
|
||||||
struct worker_pool *cpu_pools =
|
struct worker_pool *cpu_pools =
|
||||||
per_cpu(cpu_worker_pools, cpu);
|
per_cpu(cpu_worker_pools, cpu);
|
||||||
|
|
||||||
pwq->pool = &cpu_pools[highpri];
|
init_and_link_pwq(pwq, wq, &cpu_pools[highpri]);
|
||||||
list_add_tail_rcu(&pwq->pwqs_node, &wq->pwqs);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
struct pool_workqueue *pwq;
|
struct pool_workqueue *pwq;
|
||||||
|
struct worker_pool *pool;
|
||||||
|
|
||||||
pwq = kmem_cache_zalloc(pwq_cache, GFP_KERNEL);
|
pwq = kmem_cache_zalloc(pwq_cache, GFP_KERNEL);
|
||||||
if (!pwq)
|
if (!pwq)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
pwq->pool = get_unbound_pool(unbound_std_wq_attrs[highpri]);
|
pool = get_unbound_pool(unbound_std_wq_attrs[highpri]);
|
||||||
if (!pwq->pool) {
|
if (!pool) {
|
||||||
kmem_cache_free(pwq_cache, pwq);
|
kmem_cache_free(pwq_cache, pwq);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_add_tail_rcu(&pwq->pwqs_node, &wq->pwqs);
|
init_and_link_pwq(pwq, wq, pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3406,7 +3423,7 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt,
|
||||||
|
|
||||||
wq = kzalloc(sizeof(*wq) + namelen, GFP_KERNEL);
|
wq = kzalloc(sizeof(*wq) + namelen, GFP_KERNEL);
|
||||||
if (!wq)
|
if (!wq)
|
||||||
goto err;
|
return NULL;
|
||||||
|
|
||||||
vsnprintf(wq->name, namelen, fmt, args1);
|
vsnprintf(wq->name, namelen, fmt, args1);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
@ -3429,18 +3446,7 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt,
|
||||||
INIT_LIST_HEAD(&wq->list);
|
INIT_LIST_HEAD(&wq->list);
|
||||||
|
|
||||||
if (alloc_and_link_pwqs(wq) < 0)
|
if (alloc_and_link_pwqs(wq) < 0)
|
||||||
goto err;
|
goto err_free_wq;
|
||||||
|
|
||||||
local_irq_disable();
|
|
||||||
for_each_pwq(pwq, wq) {
|
|
||||||
BUG_ON((unsigned long)pwq & WORK_STRUCT_FLAG_MASK);
|
|
||||||
pwq->wq = wq;
|
|
||||||
pwq->flush_color = -1;
|
|
||||||
pwq->max_active = max_active;
|
|
||||||
INIT_LIST_HEAD(&pwq->delayed_works);
|
|
||||||
INIT_LIST_HEAD(&pwq->mayday_node);
|
|
||||||
}
|
|
||||||
local_irq_enable();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Workqueues which may be used during memory reclaim should
|
* Workqueues which may be used during memory reclaim should
|
||||||
|
@ -3449,16 +3455,19 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt,
|
||||||
if (flags & WQ_MEM_RECLAIM) {
|
if (flags & WQ_MEM_RECLAIM) {
|
||||||
struct worker *rescuer;
|
struct worker *rescuer;
|
||||||
|
|
||||||
wq->rescuer = rescuer = alloc_worker();
|
rescuer = alloc_worker();
|
||||||
if (!rescuer)
|
if (!rescuer)
|
||||||
goto err;
|
goto err_destroy;
|
||||||
|
|
||||||
rescuer->rescue_wq = wq;
|
rescuer->rescue_wq = wq;
|
||||||
rescuer->task = kthread_create(rescuer_thread, rescuer, "%s",
|
rescuer->task = kthread_create(rescuer_thread, rescuer, "%s",
|
||||||
wq->name);
|
wq->name);
|
||||||
if (IS_ERR(rescuer->task))
|
if (IS_ERR(rescuer->task)) {
|
||||||
goto err;
|
kfree(rescuer);
|
||||||
|
goto err_destroy;
|
||||||
|
}
|
||||||
|
|
||||||
|
wq->rescuer = rescuer;
|
||||||
rescuer->task->flags |= PF_THREAD_BOUND;
|
rescuer->task->flags |= PF_THREAD_BOUND;
|
||||||
wake_up_process(rescuer->task);
|
wake_up_process(rescuer->task);
|
||||||
}
|
}
|
||||||
|
@ -3479,12 +3488,12 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt,
|
||||||
spin_unlock_irq(&workqueue_lock);
|
spin_unlock_irq(&workqueue_lock);
|
||||||
|
|
||||||
return wq;
|
return wq;
|
||||||
err:
|
|
||||||
if (wq) {
|
err_free_wq:
|
||||||
free_pwqs(wq);
|
|
||||||
kfree(wq->rescuer);
|
|
||||||
kfree(wq);
|
kfree(wq);
|
||||||
}
|
return NULL;
|
||||||
|
err_destroy:
|
||||||
|
destroy_workqueue(wq);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__alloc_workqueue_key);
|
EXPORT_SYMBOL_GPL(__alloc_workqueue_key);
|
||||||
|
@ -3526,7 +3535,7 @@ void destroy_workqueue(struct workqueue_struct *wq)
|
||||||
* wq list is used to freeze wq, remove from list after
|
* wq list is used to freeze wq, remove from list after
|
||||||
* flushing is complete in case freeze races us.
|
* flushing is complete in case freeze races us.
|
||||||
*/
|
*/
|
||||||
list_del(&wq->list);
|
list_del_init(&wq->list);
|
||||||
|
|
||||||
spin_unlock_irq(&workqueue_lock);
|
spin_unlock_irq(&workqueue_lock);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue