diff options
author | Arnd Bergmann <arnd@arndb.de> | 2006-01-04 19:31:24 (GMT) |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-01-09 04:44:39 (GMT) |
commit | 5ef8224aaa9220bfecb362f0802cf78aad47c02a (patch) | |
tree | 3288b9510d4ab36d627cf85f1b4160a6d8ff9823 /arch | |
parent | e80358ad8606382154d97165121602dfae213e4a (diff) | |
download | linux-5ef8224aaa9220bfecb362f0802cf78aad47c02a.tar.xz |
[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.c | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/file.c | 15 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/spufs.h | 1 |
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 903c35d..c5cd55a 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) 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); diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 9738de7..e634268 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, { 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; } diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 420953b..b504744 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h @@ -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; |