[Cbe-oss-dev] [patch 07/10] spufs: add kernel support for spu task
Arnd Bergmann
arnd at arndb.de
Thu Aug 30 00:19:42 EST 2007
On Wednesday 29 August 2007, Sebastian Siewior wrote:
> I tried. What about:
better, but I think you can do more:
> static void setup_spu_sched(struct spu_context *ctx)
> {
> if (ctx->state == SPU_STATE_SAVED) {
> __spu_update_sched_info(ctx);
> spu_set_timeslice(ctx);
> spu_activate(ctx, 0);
> } else {
> /*
> * We have to update the scheduling priority under active_mutex
> * to protect against find_victim().
> */
> spu_update_sched_info(ctx);
> }
> }
>
> static void check_spu_state(struct kspu_context *kctx, unsigned int *npc,
> unsigned int *status)
> {
> if (!(*status & SPU_STATUS_RUNNING)) {
> /* spu is currently not running */
> pr_debug("SPU not running, last stop code was: %08x\n",
> *status >> SPU_STOP_STATUS_SHIFT);
> if (pending_spu_work(kctx)) {
> /* spu should run again */
> pr_debug("Activate SPU\n");
> kspu_fill_dummy_reqs(kctx);
>
> spu_run_fini(kctx->spu_ctx, npc, status);
> spu_acquire_runnable(kctx->spu_ctx, 0);
> spu_run_init(kctx->spu_ctx, npc);
> } else {
> /* spu finished work */
> pr_debug("SPU will remain in stop state\n");
> spu_run_fini(kctx->spu_ctx, npc, status);
> spu_yield(kctx->spu_ctx);
> spu_acquire(kctx->spu_ctx);
> }
> } else {
> pr_debug("SPU is running, switch state to util user\n");
> spuctx_switch_state(kctx->spu_ctx, SPU_UTIL_USER);
> }
> }
>
> /*
> * based on run.c spufs_run_spu
> */
> static int spufs_run_kernel_spu(void *priv)
> {
> struct kspu_context *kctx = (struct kspu_context *) priv;
> struct spu_context *ctx = kctx->spu_ctx;
> int ret;
> u32 status;
> unsigned int npc = 0;
> int fastpath;
> DEFINE_WAIT(wait_for_stop);
> DEFINE_WAIT(wait_for_ibox);
> DEFINE_WAIT(wait_for_newitem);
>
> ctx->event_return = 0;
> spu_acquire(ctx);
> ctx->ops->master_start(ctx);
>
> setup_spu_sched(ctx);
>
> spu_run_init(ctx, &npc);
> do {
> fastpath = 0;
> prepare_to_wait(&ctx->stop_wq, &wait_for_stop,
> TASK_INTERRUPTIBLE);
> prepare_to_wait(&ctx->ibox_wq, &wait_for_ibox,
> TASK_INTERRUPTIBLE);
> prepare_to_wait(&kctx->newitem_wq, &wait_for_newitem,
> TASK_INTERRUPTIBLE);
Everything from here
> if (unlikely(test_and_clear_bit(SPU_SCHED_NOTIFY_ACTIVE,
> &ctx->sched_flags))) {
> if (!(status & SPU_STATUS_STOPPED_BY_STOP)) {
> spu_switch_notify(ctx->spu, ctx);
> }
> }
>
> spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);
>
> pr_debug("going to handle class1\n");
> ret = spufs_handle_class1(ctx);
> if (unlikely(ret)) {
> /*
> * SPE_EVENT_SPE_DATA_STORAGE => refernce invalid memory
> */
> printk(KERN_ERR "Invalid memory dereferenced by the"
> "spu: %d\n", ret);
> BUG();
> }
>
> /* FIXME BUG: We need a physical SPU to discover
> * ctx->spu->class_0_pending. It is not saved on context
> * switch. We may lose this on context switch.
> */
> status = ctx->ops->status_read(ctx);
> if (unlikely((ctx->spu && ctx->spu->class_0_pending) ||
> status & SPU_STATUS_INVALID_INSTR)) {
> printk(KERN_ERR "kspu error, status_register: 0x%08x\n",
> status);
> printk(KERN_ERR "event return: 0x%08lx, spu's npc: "
> "0x%08x\n", kctx->spu_ctx->event_return,
> kctx->spu_ctx->ops->npc_read(
> kctx->spu_ctx));
> printk(KERN_ERR "class_0_pending: 0x%x\n", ctx->spu->class_0_pending);
> print_kctx_debug(kctx);
> BUG();
> }
>
> if (notify_done_reqs(kctx))
> fastpath = 1;
>
> if (queue_requests(kctx))
> fastpath = 1;
>
> check_spu_state(kctx, &npc, &status);
to here can probably go into a separate function.
> if (fastpath)
> continue;
with fastpath being the return value of that function, so you end up with
if (spufs_process_kspu_events(ctx))
continue;
You might need more arguments there, but try to avoid them.
> spu_release(ctx);
> schedule();
> spu_acquire(ctx);
>
> } while (!kthread_should_stop() || !list_empty(&kctx->work_queue));
>
> finish_wait(&ctx->stop_wq, &wait_for_stop);
> finish_wait(&ctx->ibox_wq, &wait_for_ibox);
> finish_wait(&kctx->newitem_wq, &wait_for_newitem);
>
> ctx->ops->master_stop(ctx);
> spu_release(ctx);
> return 0;
> }
Arnd <><
More information about the cbe-oss-dev
mailing list