[PATCH] spufs: serialize sys_spu_run per spu
authorArnd Bergmann <arnd@arndb.de>
Wed, 4 Jan 2006 19:31:24 +0000 (20:31 +0100)
committerPaul Mackerras <paulus@samba.org>
Mon, 9 Jan 2006 04:44:39 +0000 (15:44 +1100)
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>
arch/powerpc/platforms/cell/spufs/context.c
arch/powerpc/platforms/cell/spufs/file.c
arch/powerpc/platforms/cell/spufs/spufs.h

index 903c35d1957766edd4390efa9459656cc1ff0c78..c5cd55ac848d2774375d1816f7df4cc1671e2872 100644 (file)
@@ -43,6 +43,7 @@ struct spu_context *alloc_spu_context(struct address_space *local_store)
        spin_lock_init(&ctx->mmio_lock);
        kref_init(&ctx->kref);
        init_rwsem(&ctx->state_sema);
+       init_MUTEX(&ctx->run_sema);
        init_waitqueue_head(&ctx->ibox_wq);
        init_waitqueue_head(&ctx->wbox_wq);
        init_waitqueue_head(&ctx->stop_wq);
index 9738de727f3222dfca189de58632a4c11e172a3b..e63426822fd522e32411db58ca6f259b4512b858 100644 (file)
@@ -620,8 +620,12 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
 {
        int ret;
 
-       if ((ret = spu_run_init(ctx, npc, status)) != 0)
-               return ret;
+       if (down_interruptible(&ctx->run_sema))
+               return -ERESTARTSYS;
+
+       ret = spu_run_init(ctx, npc, status);
+       if (ret)
+               goto out;
 
        do {
                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,
                        break;
                if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
                        ret = spu_reacquire_runnable(ctx, npc, status);
-                       if (ret) {
-                               return ret;
-                       }
+                       if (ret)
+                               goto out;
                        continue;
                }
                ret = spu_process_events(ctx);
@@ -645,6 +648,8 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
                ret = *status;
        spu_yield(ctx);
 
+out:
+       up(&ctx->run_sema);
        return ret;
 }
 
index 420953b5888183f147ff7108018734b68322fe68..b504744508198dcb82301dd9cfc81843a12e04e1 100644 (file)
@@ -48,6 +48,7 @@ struct spu_context {
 
        enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state;
        struct rw_semaphore state_sema;
+       struct semaphore run_sema;
 
        struct mm_struct *owner;