Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=0887309589824fb1c3744c69a330c99c369124a0
Commit:     0887309589824fb1c3744c69a330c99c369124a0
Parent:     390cbb56a731546edc0f35fbc4c5045676467581
Author:     Christoph Hellwig <[EMAIL PROTECTED]>
AuthorDate: Mon Apr 23 21:08:06 2007 +0200
Committer:  Arnd Bergmann <[EMAIL PROTECTED]>
CommitDate: Mon Apr 23 21:18:52 2007 +0200

    [POWERPC] spufs: use cancel_rearming_delayed_workqueue when stopping spu 
contexts
    
    The scheduler workqueue may rearm itself and deadlock when we try to stop
    it.  Put a flag in place to avoid skip the work if we're tearing down
    the context.
    
    Signed-off-by: Christoph Hellwig <[EMAIL PROTECTED]>
    Signed-off-by: Arnd Bergmann <[EMAIL PROTECTED]>
---
 arch/powerpc/platforms/cell/spufs/sched.c |   25 ++++++++++++++++++++++---
 arch/powerpc/platforms/cell/spufs/spufs.h |    2 +-
 2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/platforms/cell/spufs/sched.c 
b/arch/powerpc/platforms/cell/spufs/sched.c
index c956158..003e330 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -71,14 +71,25 @@ static inline int node_allowed(int node)
 
 void spu_start_tick(struct spu_context *ctx)
 {
-       if (ctx->policy == SCHED_RR)
+       if (ctx->policy == SCHED_RR) {
+               /*
+                * Make sure the exiting bit is cleared.
+                */
+               clear_bit(SPU_SCHED_EXITING, &ctx->sched_flags);
                queue_delayed_work(spu_sched_wq, &ctx->sched_work, 
SPU_TIMESLICE);
+       }
 }
 
 void spu_stop_tick(struct spu_context *ctx)
 {
-       if (ctx->policy == SCHED_RR)
+       if (ctx->policy == SCHED_RR) {
+               /*
+                * While the work can be rearming normally setting this flag
+                * makes sure it does not rearm itself anymore.
+                */
+               set_bit(SPU_SCHED_EXITING, &ctx->sched_flags);
                cancel_delayed_work(&ctx->sched_work);
+       }
 }
 
 void spu_sched_tick(struct work_struct *work)
@@ -88,6 +99,14 @@ void spu_sched_tick(struct work_struct *work)
        struct spu *spu;
        int rearm = 1;
 
+       /*
+        * If this context is being stopped avoid rescheduling from the
+        * scheduler tick because we would block on the state_mutex.
+        * The caller will yield the spu later on anyway.
+        */
+       if (test_bit(SPU_SCHED_EXITING, &ctx->sched_flags))
+               return;
+
        mutex_lock(&ctx->state_mutex);
        spu = ctx->spu;
        if (spu) {
@@ -377,7 +396,7 @@ static struct spu *find_victim(struct spu_context *ctx)
  * @ctx:       spu context to schedule
  * @flags:     flags (currently ignored)
  *
- * Tries to find a free spu to run @ctx.  If no free spu is availble
+ * Tries to find a free spu to run @ctx.  If no free spu is available
  * add the context to the runqueue so it gets woken up once an spu
  * is available.
  */
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h 
b/arch/powerpc/platforms/cell/spufs/spufs.h
index 5c4e47d..f418378 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -41,7 +41,7 @@ struct spu_gang;
 
 /* ctx->sched_flags */
 enum {
-       SPU_SCHED_WAKE = 0, /* currently unused */
+       SPU_SCHED_EXITING = 0,
 };
 
 struct spu_context {
-
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