[Cbe-oss-dev] Scheduler runqueue interactions

Luke Browning LukeBrowning at us.ibm.com
Sun Feb 25 01:16:27 EST 2007





Hi Christoph,

See comment below subroutine.

Thanks, Luke


/**
 * spu_activate - find a free spu for a context and execute it
 * @ctx:        spu context to schedule
 * @flags:      flags (currently ignored)
 *
 * Tries to find a free spu to run @ctx.  If no free spu is availble
 * add the context to the runqueue so it gets woken up once an spu
 * is available.
 */
int spu_activate(struct spu_context *ctx, unsigned long flags)
{

        if (ctx->spu)
                return 0;

        do {
                struct spu *spu;

                spu = spu_get_idle(ctx);
                /*
                 * If this is a realtime thread we try to get it running by
                 * preempting a lower priority thread.
                 */
                if (!spu && ctx->rt_priority)
                        spu = find_victim(ctx);
                if (spu) {
                        spu_bind_context(spu, ctx);
                        return 0;
                }

                spu_add_to_rq(ctx);
                if (!(flags & SPU_ACTIVATE_NOWAKE))
                        spu_prio_wait(ctx);
                spu_del_from_rq(ctx);
        } while (!signal_pending(current));

        return -ERESTARTSYS;
}

--------------------------

A couple of points:

1) If ctx is not fixed priority (ie. SCHED_OTHER) and SPU_ACTIVATE_NOWAKE
is specified (spu_run_init)
    then you spin waiting for an spu to become idle assuming there is not a
signal pending.

      do {
            ...
            spu_add_to_rq()
            spu_del_from_rq()
      } while (!signal);

2) SPU_ACTIVATE_NOWAKE is a bad name as it doesn't describe what the target
is doing.   In this case
    the caller is requesting that ctx be put into the runnable state
without blocking.   I suggest something like:

      if (!(flags & SPU_ACTIVATE_NDELAY))
            spu_prio_wait()

    Sorry to belabour this point, but I made it in my earlier comment.
Maybe it wasn't clear.

3) this is actually the big point.  The high level flow should be:

      spufs_run_spu()
      {
            spu_run_init();                     <--- the ctx is made
runnable w/o blocking.

            do {
                  spufs_wait();                 <--- the calling thread
blocks here for the first time.
                  ...
            } while ();
      }

We want to avoid the context switch in spu_run_init(), since we are going
to block a few lines of code
later in spufs_run_spu() when it invokes spufs_wait().   We might as well
just wait there the first time.
spu_run_init() should just put the ctx on the runqueue and return to the
caller w/o blocking.

Here's the tricky part.  spu_run_init() also performs runctl register
stuff!   I think that these state changes
can be made against the saved state of the ctx and applied later by the
scheduler just as it would for
a preempted context, so these changes do not require a major restructuring
of the code.  The ctx should
be put on the runqueue with its save area updated just like you would have
if it were preempted.

Luke
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ozlabs.org/pipermail/cbe-oss-dev/attachments/20070224/9946d945/attachment.htm>


More information about the cbe-oss-dev mailing list