Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 316722
b: refs/heads/master
c: 3ce6337
h: refs/heads/master
v: v3
  • Loading branch information
Tejun Heo committed Jul 17, 2012
1 parent b283983 commit db4ac91
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 81 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 25511a477657884d2164f338341fa89652610507
refs/heads/master: 3ce63377305b694f53e7dd0c72907591c5344224
94 changes: 14 additions & 80 deletions trunk/kernel/workqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ struct worker_pool {

struct mutex manager_mutex; /* mutex manager should hold */
struct ida worker_ida; /* L: for worker IDs */
struct worker *first_idle; /* L: first idle worker */
};

/*
Expand Down Expand Up @@ -3477,24 +3476,13 @@ static void gcwq_release_management(struct global_cwq *gcwq)
__ret1 < 0 ? -1 : 0; \
})

static bool gcwq_has_idle_workers(struct global_cwq *gcwq)
{
struct worker_pool *pool;

for_each_worker_pool(pool, gcwq)
if (!list_empty(&pool->idle_list))
return true;
return false;
}

static int __cpuinit trustee_thread(void *__gcwq)
{
struct global_cwq *gcwq = __gcwq;
struct worker_pool *pool;
struct worker *worker;
struct work_struct *work;
struct hlist_node *pos;
long rc;
int i;

BUG_ON(gcwq->cpu != smp_processor_id());
Expand Down Expand Up @@ -3597,25 +3585,6 @@ static int __cpuinit trustee_thread(void *__gcwq)
break;
}

/*
* Either all works have been scheduled and cpu is down, or
* cpu down has already been canceled. Wait for and butcher
* all workers till we're canceled.
*/
do {
rc = trustee_wait_event(gcwq_has_idle_workers(gcwq));

i = 0;
for_each_worker_pool(pool, gcwq) {
while (!list_empty(&pool->idle_list)) {
worker = list_first_entry(&pool->idle_list,
struct worker, entry);
destroy_worker(worker);
}
i |= pool->nr_workers;
}
} while (i && rc >= 0);

gcwq_release_management(gcwq);

/* notify completion */
Expand Down Expand Up @@ -3658,10 +3627,8 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
unsigned int cpu = (unsigned long)hcpu;
struct global_cwq *gcwq = get_gcwq(cpu);
struct task_struct *new_trustee = NULL;
struct worker *new_workers[NR_WORKER_POOLS] = { };
struct worker_pool *pool;
unsigned long flags;
int i;

action &= ~CPU_TASKS_FROZEN;

Expand All @@ -3672,14 +3639,22 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
if (IS_ERR(new_trustee))
return notifier_from_errno(PTR_ERR(new_trustee));
kthread_bind(new_trustee, cpu);
/* fall through */
break;

case CPU_UP_PREPARE:
i = 0;
for_each_worker_pool(pool, gcwq) {
BUG_ON(pool->first_idle);
new_workers[i] = create_worker(pool);
if (!new_workers[i++])
goto err_destroy;
struct worker *worker;

if (pool->nr_workers)
continue;

worker = create_worker(pool);
if (!worker)
return NOTIFY_BAD;

spin_lock_irq(&gcwq->lock);
start_worker(worker);
spin_unlock_irq(&gcwq->lock);
}
}

Expand All @@ -3694,23 +3669,10 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
gcwq->trustee_state = TRUSTEE_START;
wake_up_process(gcwq->trustee);
wait_trustee_state(gcwq, TRUSTEE_IN_CHARGE);
/* fall through */
case CPU_UP_PREPARE:
i = 0;
for_each_worker_pool(pool, gcwq) {
BUG_ON(pool->first_idle);
pool->first_idle = new_workers[i++];
}
break;

case CPU_POST_DEAD:
gcwq->trustee_state = TRUSTEE_BUTCHER;
/* fall through */
case CPU_UP_CANCELED:
for_each_worker_pool(pool, gcwq) {
destroy_worker(pool->first_idle);
pool->first_idle = NULL;
}
break;

case CPU_DOWN_FAILED:
Expand All @@ -3730,39 +3692,12 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
rebind_workers(gcwq);

gcwq_release_management(gcwq);

/*
* Trustee is done and there might be no worker left.
* Put the first_idle in and request a real manager to
* take a look.
*/
for_each_worker_pool(pool, gcwq) {
spin_unlock_irq(&gcwq->lock);
kthread_bind(pool->first_idle->task, cpu);
spin_lock_irq(&gcwq->lock);
pool->flags |= POOL_MANAGE_WORKERS;
pool->first_idle->flags &= ~WORKER_UNBOUND;
start_worker(pool->first_idle);
pool->first_idle = NULL;
}
break;
}

spin_unlock_irqrestore(&gcwq->lock, flags);

return notifier_from_errno(0);

err_destroy:
if (new_trustee)
kthread_stop(new_trustee);

spin_lock_irqsave(&gcwq->lock, flags);
for (i = 0; i < NR_WORKER_POOLS; i++)
if (new_workers[i])
destroy_worker(new_workers[i]);
spin_unlock_irqrestore(&gcwq->lock, flags);

return NOTIFY_BAD;
}

/*
Expand All @@ -3775,7 +3710,6 @@ static int __devinit workqueue_cpu_up_callback(struct notifier_block *nfb,
{
switch (action & ~CPU_TASKS_FROZEN) {
case CPU_UP_PREPARE:
case CPU_UP_CANCELED:
case CPU_DOWN_FAILED:
case CPU_ONLINE:
return workqueue_cpu_callback(nfb, action, hcpu);
Expand Down

0 comments on commit db4ac91

Please sign in to comment.