fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / powerpc / platforms / cell / spufs / context.c
index 8bb33ab..0870009 100644 (file)
 #include <asm/spu_csa.h>
 #include "spufs.h"
 
-struct spu_context *alloc_spu_context(void)
+struct spu_context *alloc_spu_context(struct spu_gang *gang)
 {
        struct spu_context *ctx;
-       ctx = kmalloc(sizeof *ctx, GFP_KERNEL);
+       ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
        if (!ctx)
                goto out;
        /* Binding to physical processor deferred
@@ -48,19 +48,11 @@ struct spu_context *alloc_spu_context(void)
        init_waitqueue_head(&ctx->wbox_wq);
        init_waitqueue_head(&ctx->stop_wq);
        init_waitqueue_head(&ctx->mfc_wq);
-       ctx->ibox_fasync = NULL;
-       ctx->wbox_fasync = NULL;
-       ctx->mfc_fasync = NULL;
-       ctx->mfc = NULL;
-       ctx->tagwait = 0;
        ctx->state = SPU_STATE_SAVED;
-       ctx->local_store = NULL;
-       ctx->cntl = NULL;
-       ctx->signal1 = NULL;
-       ctx->signal2 = NULL;
-       ctx->spu = NULL;
        ctx->ops = &spu_backing_ops;
        ctx->owner = get_task_mm(current);
+       if (gang)
+               spu_gang_add_ctx(gang, ctx);
        goto out;
 out_free:
        kfree(ctx);
@@ -77,6 +69,8 @@ void destroy_spu_context(struct kref *kref)
        spu_deactivate(ctx);
        up_write(&ctx->state_sema);
        spu_fini_csa(&ctx->csa);
+       if (ctx->gang)
+               spu_gang_remove_ctx(ctx->gang, ctx);
        kfree(ctx);
 }
 
@@ -126,6 +120,33 @@ void spu_unmap_mappings(struct spu_context *ctx)
                unmap_mapping_range(ctx->signal2, 0, 0x4000, 1);
 }
 
+int spu_acquire_exclusive(struct spu_context *ctx)
+{
+       int ret = 0;
+
+       down_write(&ctx->state_sema);
+       /* ctx is about to be freed, can't acquire any more */
+       if (!ctx->owner) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (ctx->state == SPU_STATE_SAVED) {
+               ret = spu_activate(ctx, 0);
+               if (ret)
+                       goto out;
+               ctx->state = SPU_STATE_RUNNABLE;
+       } else {
+               /* We need to exclude userspace access to the context. */
+               spu_unmap_mappings(ctx);
+       }
+
+out:
+       if (ret)
+               up_write(&ctx->state_sema);
+       return ret;
+}
+
 int spu_acquire_runnable(struct spu_context *ctx)
 {
        int ret = 0;