aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorAndre Detsch <adetsch@br.ibm.com>2008-07-23 20:57:26 -0400
committerJeremy Kerr <jk@ozlabs.org>2008-07-23 20:57:26 -0400
commit0855b543222e79cbbd9d66dd56cb54740e7d524f (patch)
tree77e6e838138d623c96e61c497417e9fc0f82100e /arch/powerpc
parent9bcab8405c98c34849c5795c717b7e6a3e2d3875 (diff)
powerpc/spufs: fix aff_mutex and cbe_spu_info[n].list_mutex deadlock
Currenlt,, it is possible to lock aff_mutex and cbe_spu_info[n].list_mutex in different orders, allowing a deadlock to occur. With this change, aff_mutex is not taken within a list_mutex critical section anymore. Signed-off-by: Andre Detsch <adetsch@br.ibm.com> Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c18
1 files changed, 6 insertions, 12 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 34654743363d..f293963cd855 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -389,6 +389,9 @@ static int has_affinity(struct spu_context *ctx)
389 if (list_empty(&ctx->aff_list)) 389 if (list_empty(&ctx->aff_list))
390 return 0; 390 return 0;
391 391
392 if (atomic_read(&ctx->gang->aff_sched_count) == 0)
393 ctx->gang->aff_ref_spu = NULL;
394
392 if (!gang->aff_ref_spu) { 395 if (!gang->aff_ref_spu) {
393 if (!(gang->aff_flags & AFF_MERGED)) 396 if (!(gang->aff_flags & AFF_MERGED))
394 aff_merge_remaining_ctxs(gang); 397 aff_merge_remaining_ctxs(gang);
@@ -416,14 +419,8 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
416 if (spu->ctx->flags & SPU_CREATE_NOSCHED) 419 if (spu->ctx->flags & SPU_CREATE_NOSCHED)
417 atomic_dec(&cbe_spu_info[spu->node].reserved_spus); 420 atomic_dec(&cbe_spu_info[spu->node].reserved_spus);
418 421
419 if (ctx->gang){ 422 if (ctx->gang)
420 mutex_lock(&ctx->gang->aff_mutex); 423 atomic_dec_if_positive(&ctx->gang->aff_sched_count);
421 if (has_affinity(ctx)) {
422 if (atomic_dec_and_test(&ctx->gang->aff_sched_count))
423 ctx->gang->aff_ref_spu = NULL;
424 }
425 mutex_unlock(&ctx->gang->aff_mutex);
426 }
427 424
428 spu_switch_notify(spu, NULL); 425 spu_switch_notify(spu, NULL);
429 spu_unmap_mappings(ctx); 426 spu_unmap_mappings(ctx);
@@ -562,10 +559,7 @@ static struct spu *spu_get_idle(struct spu_context *ctx)
562 goto found; 559 goto found;
563 mutex_unlock(&cbe_spu_info[node].list_mutex); 560 mutex_unlock(&cbe_spu_info[node].list_mutex);
564 561
565 mutex_lock(&ctx->gang->aff_mutex); 562 atomic_dec(&ctx->gang->aff_sched_count);
566 if (atomic_dec_and_test(&ctx->gang->aff_sched_count))
567 ctx->gang->aff_ref_spu = NULL;
568 mutex_unlock(&ctx->gang->aff_mutex);
569 goto not_found; 563 goto not_found;
570 } 564 }
571 mutex_unlock(&ctx->gang->aff_mutex); 565 mutex_unlock(&ctx->gang->aff_mutex);