int spu_acquire_runnable(struct spu_context *ctx) { int ret = 0; down_read(&ctx->state_sema); if (ctx->state == SPU_STATE_RUNNABLE) { ctx->spu->prio = current->prio; return 0; } up_read(&ctx->state_sema); 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; } downgrade_write(&ctx->state_sema); /* On success, we return holding the lock */ return ret; out: /* Release here, to simplify calling code. */ up_write(&ctx->state_sema); return ret; }
/** * spu_acquire_exclusive - lock spu contex and protect against userspace access * @ctx: spu contex to lock * * Note: * Returns 0 and with the context locked on success * Returns negative error and with the context _unlocked_ on failure. */ int spu_acquire_exclusive(struct spu_context *ctx) { int ret = -EINVAL; spu_acquire(ctx); /* * Context is about to be freed, so we can't acquire it anymore. */ if (!ctx->owner) goto out_unlock; if (ctx->state == SPU_STATE_SAVED) { ret = spu_activate(ctx, 0); if (ret) goto out_unlock; } else { /* * We need to exclude userspace access to the context. * * To protect against memory access we invalidate all ptes * and make sure the pagefault handlers block on the mutex. */ spu_unmap_mappings(ctx); } return 0; out_unlock: spu_release(ctx); return ret; }
/** * spu_release_saved - unlock spu context and return it to the runqueue * @ctx: context to unlock */ void spu_release_saved(struct spu_context *ctx) { BUG_ON(ctx->state != SPU_STATE_SAVED); if (test_and_clear_bit(SPU_SCHED_WAS_ACTIVE, &ctx->sched_flags) && test_bit(SPU_SCHED_SPU_RUN, &ctx->sched_flags)) spu_activate(ctx, 0); spu_release(ctx); }
/** * spu_acquire_runnable - lock spu contex and make sure it is in runnable state * @ctx: spu contex to lock * * Note: * Returns 0 and with the context locked on success * Returns negative error and with the context _unlocked_ on failure. */ int spu_acquire_runnable(struct spu_context *ctx, unsigned long flags) { int ret = -EINVAL; spu_acquire(ctx); if (ctx->state == SPU_STATE_SAVED) { /* * Context is about to be freed, so we can't acquire it anymore. */ if (!ctx->owner) goto out_unlock; ret = spu_activate(ctx, flags); if (ret) goto out_unlock; } return 0; out_unlock: spu_release(ctx); return ret; }