[Cbe-oss-dev] [PATCH] powerpc/spufs: fix race for a free SPU
Christoph Hellwig
hch at lst.de
Fri Sep 5 08:49:55 EST 2008
On Thu, Sep 04, 2008 at 05:50:24PM +1000, Jeremy Kerr wrote:
> We currently have a race for a free SPE. With one thread doing a
> spu_yield(), and another doing a spu_activate():
>
> thread 1 thread 2
> spu_yield(oldctx) spu_activate(ctx)
> __spu_deactivate(oldctx)
> spu_unschedule(oldctx, spu)
> spu->alloc_state = SPU_FREE
> spu = spu_get_idle(ctx)
> - searches for a SPE in
> state SPU_FREE, gets
> the context just
> freed by thread 1
> spu_schedule(ctx, spu)
> spu->alloc_state = SPU_USED
> spu_schedule(newctx, spu)
> - tries schedule context on
> already-used spu
>
> This change introduces a 'free_spu' flag to spu_unschedule, to indicate
> whether or not the function should free the spu after descheduling the
> context. We only set this flag if we're not going to re-schedule
> another context on this SPU.
Makese sense, we should never mark the spu free if we actually have
a candiata context for it.
> @@ -838,7 +853,7 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio)
> if (spu) {
> new = grab_runnable_context(max_prio, spu->node);
> if (new || force) {
> - spu_unschedule(spu, ctx);
> + spu_unschedule(spu, ctx, new == NULL);
> if (new) {
> if (new->flags & SPU_CREATE_NOSCHED)
> wake_up(&new->stop_wq);
Maybe this should be come:
new = grab_runnable_context(max_prio, spu->node);
if (new) {
spu_unschedule(spu, ctx, 0);
if (new->flags & SPU_CREATE_NOSCHED)
wake_up(&new->stop_wq);
else {
spu_release(ctx);
spu_schedule(spu, new);
mutex_lock(&ctx->state_mutex);
}
} else if (force) {
/* spu is actually unused now */
spu_unschedule(spu, ctx, 1);
}
More information about the cbe-oss-dev
mailing list