提交 08873095 编写于 作者: C Christoph Hellwig 提交者: Arnd Bergmann

[POWERPC] spufs: use cancel_rearming_delayed_workqueue when stopping spu contexts

The scheduler workqueue may rearm itself and deadlock when we try to stop
it.  Put a flag in place to avoid skip the work if we're tearing down
the context.
Signed-off-by: NChristoph Hellwig <hch@lst.de>
Signed-off-by: NArnd Bergmann <arnd.bergmann@de.ibm.com>
上级 390cbb56
...@@ -71,14 +71,25 @@ static inline int node_allowed(int node) ...@@ -71,14 +71,25 @@ static inline int node_allowed(int node)
void spu_start_tick(struct spu_context *ctx) void spu_start_tick(struct spu_context *ctx)
{ {
if (ctx->policy == SCHED_RR) if (ctx->policy == SCHED_RR) {
/*
* Make sure the exiting bit is cleared.
*/
clear_bit(SPU_SCHED_EXITING, &ctx->sched_flags);
queue_delayed_work(spu_sched_wq, &ctx->sched_work, SPU_TIMESLICE); queue_delayed_work(spu_sched_wq, &ctx->sched_work, SPU_TIMESLICE);
}
} }
void spu_stop_tick(struct spu_context *ctx) void spu_stop_tick(struct spu_context *ctx)
{ {
if (ctx->policy == SCHED_RR) if (ctx->policy == SCHED_RR) {
/*
* While the work can be rearming normally setting this flag
* makes sure it does not rearm itself anymore.
*/
set_bit(SPU_SCHED_EXITING, &ctx->sched_flags);
cancel_delayed_work(&ctx->sched_work); cancel_delayed_work(&ctx->sched_work);
}
} }
void spu_sched_tick(struct work_struct *work) void spu_sched_tick(struct work_struct *work)
...@@ -88,6 +99,14 @@ void spu_sched_tick(struct work_struct *work) ...@@ -88,6 +99,14 @@ void spu_sched_tick(struct work_struct *work)
struct spu *spu; struct spu *spu;
int rearm = 1; int rearm = 1;
/*
* If this context is being stopped avoid rescheduling from the
* scheduler tick because we would block on the state_mutex.
* The caller will yield the spu later on anyway.
*/
if (test_bit(SPU_SCHED_EXITING, &ctx->sched_flags))
return;
mutex_lock(&ctx->state_mutex); mutex_lock(&ctx->state_mutex);
spu = ctx->spu; spu = ctx->spu;
if (spu) { if (spu) {
...@@ -377,7 +396,7 @@ static struct spu *find_victim(struct spu_context *ctx) ...@@ -377,7 +396,7 @@ static struct spu *find_victim(struct spu_context *ctx)
* @ctx: spu context to schedule * @ctx: spu context to schedule
* @flags: flags (currently ignored) * @flags: flags (currently ignored)
* *
* Tries to find a free spu to run @ctx. If no free spu is availble * Tries to find a free spu to run @ctx. If no free spu is available
* add the context to the runqueue so it gets woken up once an spu * add the context to the runqueue so it gets woken up once an spu
* is available. * is available.
*/ */
......
...@@ -41,7 +41,7 @@ struct spu_gang; ...@@ -41,7 +41,7 @@ struct spu_gang;
/* ctx->sched_flags */ /* ctx->sched_flags */
enum { enum {
SPU_SCHED_WAKE = 0, /* currently unused */ SPU_SCHED_EXITING = 0,
}; };
struct spu_context { struct spu_context {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册