<html><body>
<p><tt>cbe-oss-dev-bounces+lukebrowning=us.ibm.com@ozlabs.org wrote on 02/09/2007 01:47:29 PM:<br>
<br>
> On Fri, Feb 09, 2007 at 12:43:01AM +0100, Christoph Hellwig wrote:<br>
> > If we start a spu context with realtime priority we want it to run<br>
> > immediately and not wait until some other lower priority thread has<br>
> > finished.  Try to find a suitable victim and use it's spu in this<br>
> > case.<br>
> <br>
> Due to a mistake in my quilt usage this is missing the changes to<br>
> context.c and spufs.h.  The full patch is below:<br>
> <br>
> Index: linux-2.6/arch/powerpc/platforms/cell/spufs/sched.c<br>
> ===================================================================<br>
> --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/sched.c   <br>
> 2007-02-09 16:08:51.000000000 +0100<br>
> +++ linux-2.6/arch/powerpc/platforms/cell/spufs/sched.c   2007-02-09<br>
> 16:08:57.000000000 +0100<br>
> @@ -282,6 +282,74 @@<br>
>  }<br>
>  <br>
>  /**<br>
> + * find_victim - find a lower priority context to preempt<br>
> + * @ctx:   canidate context for running<br>
> + *<br>
> + * Returns the freed physical spu to run the new context on.<br>
> + */<br>
> +static struct spu *find_victim(struct spu_context *ctx)<br>
> +{<br>
> +   struct spu_context *victim = NULL;<br>
> +   struct spu *spu;<br>
> +   int node, n;<br>
> +<br>
> +   /*<br>
> +    * Look for a possible preemption candidate on the local node first.<br>
> +    * If there is no candidate look at the other nodes.  This isn't<br>
> +    * exactly fair, but so far the whole spu schedule tries to keep<br>
> +    * a strong node affinity.  We might want to fine-tune this in<br>
> +    * the future.<br>
> +    */<br>
> + restart:<br>
> +   node = cpu_to_node(raw_smp_processor_id());<br>
> +   for (n = 0; n < MAX_NUMNODES; n++, node++) {<br>
> +      node = (node < MAX_NUMNODES) ? node : 0;<br>
> +      if (!node_allowed(node))<br>
> +         continue;<br>
> +<br>
> +      mutex_lock(&spu_prio->active_mutex[node]);<br>
> +      list_for_each_entry(spu, &spu_prio->active_list[node], list) {<br>
> +         struct spu_context *tmp = spu->ctx;<br>
> +<br>
> +         if (tmp->rt_priority < ctx->rt_priority &&<br>
> +             (!victim || tmp->rt_priority < victim->rt_priority))<br>
> +            victim = spu->ctx;<br>
> +      }<br>
> +      mutex_unlock(&spu_prio->active_mutex[node]);<br>
> +<br>
> +      if (victim) {<br>
> +         /*<br>
> +          * This nests ctx->state_mutex, but we always lock<br>
> +          * higher priority contexts before lower priority<br>
> +          * ones, so this is safe until we introduce<br>
> +          * priority inheritance schemes.<br>
> +          */<br>
> +         if (!mutex_trylock(&victim->state_mutex)) {<br>
> +            victim = NULL;<br>
> +            goto restart;<br>
> +         }<br>
> +<br>
> +         spu = victim->spu;<br>
> +         if (!spu) {<br>
</tt><br>
<tt>You might also want to retest the priority fields under the ctx lock to </tt><br>
<tt>make ensure that the priorities haven't changed.  The code above uses the</tt><br>
<tt>runqueue lock, which doesn't protect these fields, right?</tt><br>
<br>
<tt>> +            /*<br>
> +             * This race can happen because we've dropped<br>
> +             * the active list mutex.  No a problem, just<br>
> +             * restart the search.<br>
> +             */<br>
> +            mutex_unlock(&victim->state_mutex);<br>
> +            victim = NULL;<br>
> +            goto restart;<br>
> +         }<br>
> +         spu_unbind_context(spu, victim);<br>
> +         mutex_unlock(&victim->state_mutex);<br>
> +         return spu;<br>
> +      }<br>
> +   }<br>
> +<br>
> +   return NULL;<br>
> +}<br>
> +<br>
> +/**<br>
>   * spu_activate - find a free spu for a context and execute it<br>
>   * @ctx:   spu context to schedule<br>
>   * @flags:   flags (currently ignored)<br>
> @@ -300,6 +368,12 @@<br>
>        struct spu *spu;<br>
>  <br>
>        spu = spu_get_idle(ctx);<br>
> +      /*<br>
> +       * If this is a realtime thread we try to get it running by<br>
> +       * preempting a lower priority thread.<br>
> +       */<br>
> +      if (!spu && ctx->rt_priority)<br>
> +         spu = find_victim(ctx);<br>
>        if (spu) {<br>
>           spu_bind_context(spu, ctx);<br>
>           return 0;<br>
> Index: linux-2.6/arch/powerpc/platforms/cell/spufs/context.c<br>
> ===================================================================<br>
> --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/context.c   <br>
> 2007-02-09 16:09:34.000000000 +0100<br>
> +++ linux-2.6/arch/powerpc/platforms/cell/spufs/context.c   <br>
> 2007-02-09 16:09:56.000000000 +0100<br>
> @@ -53,6 +53,7 @@<br>
>     ctx->owner = get_task_mm(current);<br>
>     if (gang)<br>
>        spu_gang_add_ctx(gang, ctx);<br>
> +   ctx->rt_priority = current->rt_priority;<br>
>     ctx->prio = current->prio;<br>
>     goto out;<br>
>  out_free:<br>
> Index: linux-2.6/arch/powerpc/platforms/cell/spufs/spufs.h<br>
> ===================================================================<br>
> --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/spufs.h   <br>
> 2007-02-09 16:09:06.000000000 +0100<br>
> +++ linux-2.6/arch/powerpc/platforms/cell/spufs/spufs.h   2007-02-09<br>
> 16:09:17.000000000 +0100<br>
> @@ -81,6 +81,7 @@<br>
>     /* scheduler fields */<br>
>      struct list_head rq;<br>
>     unsigned long sched_flags;<br>
> +   unsigned long rt_priority;<br>
>     int prio;<br>
>  };<br>
>  <br>
> _______________________________________________<br>
> cbe-oss-dev mailing list<br>
> cbe-oss-dev@ozlabs.org<br>
> <a href="https://ozlabs.org/mailman/listinfo/cbe-oss-dev">https://ozlabs.org/mailman/listinfo/cbe-oss-dev</a><br>
</tt></body></html>