aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2006-01-04 14:31:24 -0500
committerPaul Mackerras <paulus@samba.org>2006-01-08 23:44:39 -0500
commit5ef8224aaa9220bfecb362f0802cf78aad47c02a (patch)
tree3288b9510d4ab36d627cf85f1b4160a6d8ff9823 /arch
parente80358ad8606382154d97165121602dfae213e4a (diff)
[PATCH] spufs: serialize sys_spu_run per spu
During an earlier cleanup, we lost the serialization of multiple spu_run calls performed on the same spu_context. In order to get this back, introduce a mutex in the spu_context that is held inside of spu_run. Noticed by Al Viro. Signed-off-by: Arnd Bergmann <arndb@de.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c1
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c15
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h1
3 files changed, 12 insertions, 5 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 903c35d19577..c5cd55ac848d 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -43,6 +43,7 @@ struct spu_context *alloc_spu_context(struct address_space *local_store)
43 spin_lock_init(&ctx->mmio_lock); 43 spin_lock_init(&ctx->mmio_lock);
44 kref_init(&ctx->kref); 44 kref_init(&ctx->kref);
45 init_rwsem(&ctx->state_sema); 45 init_rwsem(&ctx->state_sema);
46 init_MUTEX(&ctx->run_sema);
46 init_waitqueue_head(&ctx->ibox_wq); 47 init_waitqueue_head(&ctx->ibox_wq);
47 init_waitqueue_head(&ctx->wbox_wq); 48 init_waitqueue_head(&ctx->wbox_wq);
48 init_waitqueue_head(&ctx->stop_wq); 49 init_waitqueue_head(&ctx->stop_wq);
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 9738de727f32..e63426822fd5 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -620,8 +620,12 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
620{ 620{
621 int ret; 621 int ret;
622 622
623 if ((ret = spu_run_init(ctx, npc, status)) != 0) 623 if (down_interruptible(&ctx->run_sema))
624 return ret; 624 return -ERESTARTSYS;
625
626 ret = spu_run_init(ctx, npc, status);
627 if (ret)
628 goto out;
625 629
626 do { 630 do {
627 ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, status)); 631 ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, status));
@@ -629,9 +633,8 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
629 break; 633 break;
630 if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { 634 if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
631 ret = spu_reacquire_runnable(ctx, npc, status); 635 ret = spu_reacquire_runnable(ctx, npc, status);
632 if (ret) { 636 if (ret)
633 return ret; 637 goto out;
634 }
635 continue; 638 continue;
636 } 639 }
637 ret = spu_process_events(ctx); 640 ret = spu_process_events(ctx);
@@ -645,6 +648,8 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
645 ret = *status; 648 ret = *status;
646 spu_yield(ctx); 649 spu_yield(ctx);
647 650
651out:
652 up(&ctx->run_sema);
648 return ret; 653 return ret;
649} 654}
650 655
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 420953b58881..b50474450819 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -48,6 +48,7 @@ struct spu_context {
48 48
49 enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state; 49 enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state;
50 struct rw_semaphore state_sema; 50 struct rw_semaphore state_sema;
51 struct semaphore run_sema;
51 52
52 struct mm_struct *owner; 53 struct mm_struct *owner;
53 54