diff options
author | Andre Detsch <adetsch@br.ibm.com> | 2008-07-23 20:57:26 -0400 |
---|---|---|
committer | Jeremy Kerr <jk@ozlabs.org> | 2008-07-23 20:57:26 -0400 |
commit | 0855b543222e79cbbd9d66dd56cb54740e7d524f (patch) | |
tree | 77e6e838138d623c96e61c497417e9fc0f82100e /arch/powerpc | |
parent | 9bcab8405c98c34849c5795c717b7e6a3e2d3875 (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.c | 18 |
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); |