summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2007-02-13 21:54:24 +0100
committerArnd Bergmann <arnd@klappe.arndb.de>2007-02-13 21:55:41 +0100
commit26bec67386dbf6ef887254e815398842e182cdcd (patch)
treecde0851af46df1b376a7af47e7c59362506cecc5 /arch
parent079cdb61614c466c939ebf74c7ef6745667bc61e (diff)
downloadlinux-26bec67386dbf6ef887254e815398842e182cdcd.tar.bz2
[POWERPC] spufs: optimize spu_run
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 <hch@lst.de> Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c4
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c4
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c4
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c10
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h13
5 files changed, 23 insertions, 12 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 88a887186303..056a8ad02385 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -163,7 +163,7 @@ int spu_acquire_exclusive(struct spu_context *ctx)
* 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;
@@ -174,7 +174,7 @@ int spu_acquire_runnable(struct spu_context *ctx)
*/
if (!ctx->owner)
goto out_unlock;
- ret = spu_activate(ctx, 0);
+ ret = spu_activate(ctx, flags);
if (ret)
goto out_unlock;
}
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index a528020baa18..c729813043a6 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -164,7 +164,7 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma,
/* error here usually means a signal.. we might want to test
* the error code more precisely though
*/
- ret = spu_acquire_runnable(ctx);
+ ret = spu_acquire_runnable(ctx, 0);
if (ret)
return NOPFN_REFAULT;
@@ -1306,7 +1306,7 @@ static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer,
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 {
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index e1647311044b..a973e79e9fdc 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -143,7 +143,7 @@ static inline int spu_run_init(struct spu_context *ctx, u32 * npc)
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 spu_context *ctx, u32 * npc)
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
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 6f8e2257c5a6..07d0d095c62a 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -247,8 +247,8 @@ static void spu_prio_wait(struct spu_context *ctx)
{
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_context *ctx)
}
__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 *spu)
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 spu_context *ctx)
* 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, u64 flags)
}
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));
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 7f5a4fc03c00..421f59167c55 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/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. */
@@ -77,6 +82,7 @@ struct spu_context {
/* scheduler fields */
struct list_head rq;
+ unsigned long sched_flags;
int prio;
};
@@ -179,10 +185,13 @@ int put_spu_context(struct spu_context *ctx);
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);