[POWERPC] spusched: Update scheduling paramters on every spu_run
authorChristoph Hellwig <hch@lst.de>
Fri, 29 Jun 2007 00:57:55 +0000 (10:57 +1000)
committerPaul Mackerras <paulus@samba.org>
Tue, 3 Jul 2007 05:24:45 +0000 (15:24 +1000)
Update scheduling information on every spu_run to allow for setting
threads to realtime priority just before running them.  This requires
some slightly ugly code in spufs_run_spu because we can just update
the information unlocked if the spu is not runnable, but we need to
acquire the active_mutex when it is runnable to protect against
find_victim.  This locking scheme requires opencoding
spu_acquire_runnable in spufs_run_spu which actually is a nice cleanup
all by itself.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
arch/powerpc/platforms/cell/spufs/context.c
arch/powerpc/platforms/cell/spufs/run.c
arch/powerpc/platforms/cell/spufs/sched.c
arch/powerpc/platforms/cell/spufs/spufs.h

index c5ec7cfc24b5a42f6bb840e569bcc7e1b7a8ed67..c778d9178e0f1fce1c7af60f9257d5034c31266a 100644 (file)
@@ -54,17 +54,6 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
        if (gang)
                spu_gang_add_ctx(gang, ctx);
 
-       /*
-        * We do our own priority calculations, so we normally want
-        * ->static_prio to start with. Unfortunately thies field
-        * contains junk for threads with a realtime scheduling
-        * policy so we have to look at ->prio in this case.
-        */
-       if (rt_prio(current->prio))
-               ctx->prio = current->prio;
-       else
-               ctx->prio = current->static_prio;
-       ctx->policy = current->policy;
        spu_set_timeslice(ctx);
        goto out;
 out_free:
index 89b02b6bfc5517405e1dcf99b63d0494538380d1..4e0db6ae0d5e17aeb8e4b487a913d7dfd2fd3925 100644 (file)
@@ -301,9 +301,22 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
        ctx->ops->master_start(ctx);
        ctx->event_return = 0;
 
-       ret = spu_acquire_runnable(ctx, 0);
-       if (ret)
-               return ret;
+       spu_acquire(ctx);
+       if (ctx->state == SPU_STATE_SAVED) {
+               __spu_update_sched_info(ctx);
+
+               ret = spu_activate(ctx, 0);
+               if (ret) {
+                       spu_release(ctx);
+                       goto out;
+               }
+       } else {
+               /*
+                * We have to update the scheduling priority under active_mutex
+                * to protect against find_victim().
+                */
+               spu_update_sched_info(ctx);
+       }
 
        ret = spu_run_init(ctx, npc);
        if (ret) {
index 002b40af4a77e5f9faee58a733df291c0a298bef..3707c7fdbdeef5127696e4c5ff8276648bdbd7ee 100644 (file)
@@ -96,6 +96,33 @@ void spu_set_timeslice(struct spu_context *ctx)
                ctx->time_slice = SCALE_PRIO(DEF_SPU_TIMESLICE, ctx->prio);
 }
 
+/*
+ * Update scheduling information from the owning thread.
+ */
+void __spu_update_sched_info(struct spu_context *ctx)
+{
+       /*
+        * We do our own priority calculations, so we normally want
+        * ->static_prio to start with. Unfortunately thies field
+        * contains junk for threads with a realtime scheduling
+        * policy so we have to look at ->prio in this case.
+        */
+       if (rt_prio(current->prio))
+               ctx->prio = current->prio;
+       else
+               ctx->prio = current->static_prio;
+       ctx->policy = current->policy;
+}
+
+void spu_update_sched_info(struct spu_context *ctx)
+{
+       int node = ctx->spu->node;
+
+       mutex_lock(&spu_prio->active_mutex[node]);
+       __spu_update_sched_info(ctx);
+       mutex_unlock(&spu_prio->active_mutex[node]);
+}
+
 static inline int node_allowed(int node)
 {
        cpumask_t mask;
index fddc59c204b5b91082b05f2308f4caa5e30ade6b..ff77f904fa3163bdd634068eec839c94e6c46f33 100644 (file)
@@ -195,6 +195,8 @@ int spu_activate(struct spu_context *ctx, unsigned long flags);
 void spu_deactivate(struct spu_context *ctx);
 void spu_yield(struct spu_context *ctx);
 void spu_set_timeslice(struct spu_context *ctx);
+void spu_update_sched_info(struct spu_context *ctx);
+void __spu_update_sched_info(struct spu_context *ctx);
 int __init spu_sched_init(void);
 void __exit spu_sched_exit(void);