Commit 5ef8224a authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Paul Mackerras

[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: default avatarArnd Bergmann <arndb@de.ibm.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent e80358ad
...@@ -43,6 +43,7 @@ struct spu_context *alloc_spu_context(struct address_space *local_store) ...@@ -43,6 +43,7 @@ struct spu_context *alloc_spu_context(struct address_space *local_store)
spin_lock_init(&ctx->mmio_lock); spin_lock_init(&ctx->mmio_lock);
kref_init(&ctx->kref); kref_init(&ctx->kref);
init_rwsem(&ctx->state_sema); init_rwsem(&ctx->state_sema);
init_MUTEX(&ctx->run_sema);
init_waitqueue_head(&ctx->ibox_wq); init_waitqueue_head(&ctx->ibox_wq);
init_waitqueue_head(&ctx->wbox_wq); init_waitqueue_head(&ctx->wbox_wq);
init_waitqueue_head(&ctx->stop_wq); init_waitqueue_head(&ctx->stop_wq);
......
...@@ -620,8 +620,12 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx, ...@@ -620,8 +620,12 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
{ {
int ret; int ret;
if ((ret = spu_run_init(ctx, npc, status)) != 0) if (down_interruptible(&ctx->run_sema))
return ret; return -ERESTARTSYS;
ret = spu_run_init(ctx, npc, status);
if (ret)
goto out;
do { do {
ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, status)); 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,9 +633,8 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
break; break;
if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
ret = spu_reacquire_runnable(ctx, npc, status); ret = spu_reacquire_runnable(ctx, npc, status);
if (ret) { if (ret)
return ret; goto out;
}
continue; continue;
} }
ret = spu_process_events(ctx); ret = spu_process_events(ctx);
...@@ -645,6 +648,8 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx, ...@@ -645,6 +648,8 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
ret = *status; ret = *status;
spu_yield(ctx); spu_yield(ctx);
out:
up(&ctx->run_sema);
return ret; return ret;
} }
......
...@@ -48,6 +48,7 @@ struct spu_context { ...@@ -48,6 +48,7 @@ struct spu_context {
enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state; enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state;
struct rw_semaphore state_sema; struct rw_semaphore state_sema;
struct semaphore run_sema;
struct mm_struct *owner; struct mm_struct *owner;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment