Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=27449971e6907ff38bde7bbc4647e55bd7309fc3
Commit:     27449971e6907ff38bde7bbc4647e55bd7309fc3
Parent:     c77239b8be74f775142d9dd01041e2ce864ba20d
Author:     Christoph Hellwig <[EMAIL PROTECTED]>
AuthorDate: Fri Jun 29 10:58:06 2007 +1000
Committer:  Paul Mackerras <[EMAIL PROTECTED]>
CommitDate: Tue Jul 3 15:24:46 2007 +1000

    [POWERPC] spusched: Fix runqueue corruption
    
    spu_activate can be called from multiple threads at the same time on
    behalf of the same spu context.  We need to make sure to only add it
    once to avoid runqueue corruption.
    
    Signed-off-by: Christoph Hellwig <[EMAIL PROTECTED]>
    Signed-off-by: Jeremy Kerr <[EMAIL PROTECTED]>
    Signed-off-by: Paul Mackerras <[EMAIL PROTECTED]>
---
 arch/powerpc/platforms/cell/spufs/sched.c |   37 ++++++++++++++++++++++-------
 1 files changed, 28 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/platforms/cell/spufs/sched.c 
b/arch/powerpc/platforms/cell/spufs/sched.c
index 2fb0e63..9fb3133 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -292,12 +292,25 @@ static void spu_unbind_context(struct spu *spu, struct 
spu_context *ctx)
  */
 static void __spu_add_to_rq(struct spu_context *ctx)
 {
-       int prio = ctx->prio;
-
-       list_add_tail(&ctx->rq, &spu_prio->runq[prio]);
-       set_bit(prio, spu_prio->bitmap);
-       if (!spu_prio->nr_waiting++)
-               __mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK);
+       /*
+        * Unfortunately this code path can be called from multiple threads
+        * on behalf of a single context due to the way the problem state
+        * mmap support works.
+        *
+        * Fortunately we need to wake up all these threads at the same time
+        * and can simply skip the runqueue addition for every but the first
+        * thread getting into this codepath.
+        *
+        * It's still quite hacky, and long-term we should proxy all other
+        * threads through the owner thread so that spu_run is in control
+        * of all the scheduling activity for a given context.
+        */
+       if (list_empty(&ctx->rq)) {
+               list_add_tail(&ctx->rq, &spu_prio->runq[ctx->prio]);
+               set_bit(ctx->prio, spu_prio->bitmap);
+               if (!spu_prio->nr_waiting++)
+                       __mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK);
+       }
 }
 
 static void __spu_del_from_rq(struct spu_context *ctx)
@@ -440,12 +453,18 @@ int spu_activate(struct spu_context *ctx, unsigned long 
flags)
 {
        spuctx_switch_state(ctx, SPUCTX_UTIL_SYSTEM);
 
-       if (ctx->spu)
-               return 0;
-
        do {
                struct spu *spu;
 
+               /*
+                * If there are multiple threads waiting for a single context
+                * only one actually binds the context while the others will
+                * only be able to acquire the state_mutex once the context
+                * already is in runnable state.
+                */
+               if (ctx->spu)
+                       return 0;
+
                spu = spu_get_idle(ctx);
                /*
                 * If this is a realtime thread we try to get it running by
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to