Subject: spufs: optimize spu_run From: Christoph Hellwig There is no need to directly wake up contexts in spu_activate when called from spu_run, so add a flag to surpress this wakeup. Signed-off-by: Christoph Hellwig Signed-off-by: Arnd Bergmann --- Index: linux-2.6/arch/powerpc/platforms/cell/spufs/spufs.h =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/spufs.h +++ linux-2.6/arch/powerpc/platforms/cell/spufs/spufs.h @@ -39,6 +39,11 @@ enum { struct spu_context_ops; struct spu_gang; +/* ctx->sched_flags */ +enum { + SPU_SCHED_WAKE = 0, +}; + struct spu_context { struct spu *spu; /* pointer to a physical SPU */ struct spu_state csa; /* SPU context save area. */ @@ -75,6 +80,7 @@ struct spu_context { /* scheduler fields */ struct list_head rq; + unsigned long sched_flags; int prio; }; @@ -177,10 +183,13 @@ int put_spu_context(struct spu_context * void spu_unmap_mappings(struct spu_context *ctx); void spu_forget(struct spu_context *ctx); -int spu_acquire_runnable(struct spu_context *ctx); +int spu_acquire_runnable(struct spu_context *ctx, unsigned long flags); void spu_acquire_saved(struct spu_context *ctx); int spu_acquire_exclusive(struct spu_context *ctx); -int spu_activate(struct spu_context *ctx, u64 flags); +enum { + SPU_ACTIVATE_NOWAKE = 1, +}; +int spu_activate(struct spu_context *ctx, unsigned long flags); void spu_deactivate(struct spu_context *ctx); void spu_yield(struct spu_context *ctx); int __init spu_sched_init(void); Index: linux-2.6/arch/powerpc/platforms/cell/spufs/sched.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/sched.c +++ linux-2.6/arch/powerpc/platforms/cell/spufs/sched.c @@ -247,8 +247,8 @@ static void spu_prio_wait(struct spu_con { DEFINE_WAIT(wait); + set_bit(SPU_SCHED_WAKE, &ctx->sched_flags); prepare_to_wait_exclusive(&ctx->stop_wq, &wait, TASK_INTERRUPTIBLE); - if (!signal_pending(current)) { mutex_unlock(&ctx->state_mutex); schedule(); @@ -256,6 +256,7 @@ static void spu_prio_wait(struct spu_con } __set_current_state(TASK_RUNNING); remove_wait_queue(&ctx->stop_wq, &wait); + clear_bit(SPU_SCHED_WAKE, &ctx->sched_flags); } /** @@ -275,7 +276,7 @@ static void spu_reschedule(struct spu *s best = sched_find_first_bit(spu_prio->bitmap); if (best < MAX_PRIO) { struct spu_context *ctx = spu_grab_context(best); - if (ctx) + if (ctx && test_bit(SPU_SCHED_WAKE, &ctx->sched_flags)) wake_up(&ctx->stop_wq); } spin_unlock(&spu_prio->runq_lock); @@ -315,7 +316,7 @@ static struct spu *spu_get_idle(struct s * add the context to the runqueue so it gets woken up once an spu * is available. */ -int spu_activate(struct spu_context *ctx, u64 flags) +int spu_activate(struct spu_context *ctx, unsigned long flags) { if (ctx->spu) @@ -331,7 +332,8 @@ int spu_activate(struct spu_context *ctx } spu_add_to_rq(ctx); - spu_prio_wait(ctx); + if (!(flags & SPU_ACTIVATE_NOWAKE)) + spu_prio_wait(ctx); spu_del_from_rq(ctx); } while (!signal_pending(current)); Index: linux-2.6/arch/powerpc/platforms/cell/spufs/context.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/context.c +++ linux-2.6/arch/powerpc/platforms/cell/spufs/context.c @@ -159,7 +159,7 @@ int spu_acquire_exclusive(struct spu_con * Returns 0 and with the context locked on success * Returns negative error and with the context _unlocked_ on failure. */ -int spu_acquire_runnable(struct spu_context *ctx) +int spu_acquire_runnable(struct spu_context *ctx, unsigned long flags) { int ret = -EINVAL; @@ -170,7 +170,7 @@ int spu_acquire_runnable(struct spu_cont */ if (!ctx->owner) goto out_unlock; - ret = spu_activate(ctx, 0); + ret = spu_activate(ctx, flags); if (ret) goto out_unlock; } Index: linux-2.6/arch/powerpc/platforms/cell/spufs/file.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/file.c +++ linux-2.6/arch/powerpc/platforms/cell/spufs/file.c @@ -168,7 +168,7 @@ static struct page *spufs_ps_nopage(stru if (offset >= ps_size) goto out; - ret = spu_acquire_runnable(ctx); + ret = spu_acquire_runnable(ctx, 0); if (ret) goto out; @@ -1309,7 +1309,7 @@ static ssize_t spufs_mfc_write(struct fi if (ret) goto out; - spu_acquire_runnable(ctx); + spu_acquire_runnable(ctx, 0); if (file->f_flags & O_NONBLOCK) { ret = ctx->ops->send_mfc_command(ctx, &cmd); } else { Index: linux-2.6/arch/powerpc/platforms/cell/spufs/run.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/run.c +++ linux-2.6/arch/powerpc/platforms/cell/spufs/run.c @@ -143,7 +143,7 @@ static inline int spu_run_init(struct sp int ret; unsigned long runcntl = SPU_RUNCNTL_RUNNABLE; - ret = spu_acquire_runnable(ctx); + ret = spu_acquire_runnable(ctx, SPU_ACTIVATE_NOWAKE); if (ret) return ret; @@ -155,7 +155,7 @@ static inline int spu_run_init(struct sp spu_release(ctx); ret = spu_setup_isolated(ctx); if (!ret) - ret = spu_acquire_runnable(ctx); + ret = spu_acquire_runnable(ctx, SPU_ACTIVATE_NOWAKE); } /* if userspace has set the runcntrl register (eg, to issue an