[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