[Rtai] Lowering the task priority doesn't work as expected

Paolo Mantegazza mantegazza at aero.polimi.it
Fri Apr 24 11:06:12 CEST 2009


Richly, Matthias wrote:
> Thanks for your answer. 
> In fact I tried to fix the problem with rt_task_yield() before. But that didn't work either. (I actually wasn't surprised that this was not working, because the description of this service states that it will just cause the task be appended at the end of its prioritie's ready queue, which shouldn't have any effect if there are no other tasks in that queue.)
> I think the problem arises, because the general assumption that the task with the highest priority is always running is violated by rt_change_prio; or is this assumption not valid in RTAI? I need to know that, because I always relied on it in my code. 
> 

As I said:
"You are right to a point nonetheless: it is not using sleep that a task 
should yield the CPU but with rt_task_yield. That needs a fix.",
so it is fixed in the CVS now. Using a very short sleep is much the same 
but the fix above is what is needed for what we have now.

 From my answer you should infer that your assumption is OK when the 
priority is changed by inheritance or by a somebody else, an application 
supervisor typically. It is not only when a task lowers its own 
priority. That does not mean that it will not be preempted if an 
interrupt comes in. It is not preempted immediatly just at a self 
lowering of its own priority. The idea is: I've done it but I want it to 
remain up to me to giving up running.

Your idea of having the same behavior whether is is a self lowering or 
not is perfectly legitimate, so you can see the above exception as a bug 
also. Let's say RTAI sees it differently, at the moment.

Paolo.


> Matthias
> 
> ________________________________
> 
> Von: mantegazza at aero.polimi.it [mailto:mantegazza at aero.polimi.it]
> Gesendet: Fr 24.04.2009 00:14
> An: Richly, Matthias
> Cc: rtai at rtai.org
> Betreff: Re: [Rtai] Lowering the task priority doesn't work as expected
> 
> 
> 
>> Hi,
>> I am dealing with linux user space apps using RTAIs LXRT feature. When I
>> lower the priority of the currently running task (via rt_change_prio),
>> this tasks is not preempted, although there are ready tasks with a higher
>> priority. Why not?
>>
> 
> Because I want a task changing its own priority to return. So it must be
> done explicitly by the task that lowered its priority, the change will
> work at the next schedule otherwise. When not in real time sleeping does
> not work because it's Linux that schedules.
> You are right to a point nonetheless: it is not using sleep that a task
> should yield the CPUm but with rt_task_yield. That needs a fix.
> 
> Paolo.
> 
>> The following example code shows the problem:
>>
>>               #define NTASKS 5
>>               #define MAINTASK_PRIO 10
>>               #define OTHER_TASKS_START_PRIO 20
>>               #define OTHER_TASKS_RUNNING_PRIO 30
>>
>>               pthread_t threads[NTASKS];
>>               SEM *barrier = NULL;
>>               int cpus_allowed = 1;
>>               int count = 0;
>>
>>               void *thread_fun(void *arg)
>>               {
>>                   RT_TASK* task = NULL;
>>                   int task_no = (int) arg;
>>
>>                   if(!(task = rt_task_init_schmod(rt_get_name(NULL),
>> OTHER_TASKS_START_PRIO, 0, 0, SCHED_FIFO, cpus_allowed))) {
>>                       printf("[ERROR] CANNOT INIT TASK.\n");
>>                       exit(1);
>>                   }
>>                   mlockall(MCL_CURRENT | MCL_FUTURE);
>>                   rt_make_hard_real_time();
>>
>>                   rt_printk("Task %d: Waiting for other tasks to initialize...\n",
>> task_no);
>>                   rt_sem_wait_barrier(barrier);
>>
>>                   // couting global var. up
>>                   rt_printk("Task %d: Counting up to %d.\n", task_no, ++count);
>>
>>                   rt_printk("Task %d: Lowering priority...\n", task_no);
>>                   rt_change_prio(task, OTHER_TASKS_RUNNING_PRIO);
>>
>>                   // the task should now be blocked until all other task lowered its
>> priority
>>                   if(count != NTASKS) {
>>                       rt_printk("Task %d: Ooops, count is %d (should be %d).\n",
>> task_no, count, NTASKS);
>>                   }
>>                   else {
>>                       rt_printk("Task %d: Count is okay.\n", task_no);
>>                   }
>>
>>                   rt_make_soft_real_time();
>>                   rt_task_delete(task);
>>
>>                   return 0;
>>               }
>>
>>               int main(void)
>>               {
>>                   RT_TASK* mainTask = NULL;
>>                   int hard_timer_running;
>>                   int i;
>>
>>                   if (!(mainTask = rt_task_init(rt_get_name(NULL), MAINTASK_PRIO, 0,
>> 0))) {
>>                       printf("CANNOT INIT MAIN TASK\n.");
>>                       exit(1);
>>                   }
>>
>>                   if (!(hard_timer_running = rt_is_hard_timer_running())) {
>>                       rt_set_oneshot_mode();
>>                       start_rt_timer(0);
>>                   }
>>
>>                   rt_make_hard_real_time();
>>
>>                   if (!(barrier = rt_sem_init(rt_get_name(NULL), NTASKS))) {
>>
>>                       printf("CANNOT INIT BARRIER SEM\n.");
>>                       exit(1);
>>
>>                   }
>>
>>                   for(i=0; i<NTASKS; i++) {
>>                       if (!(threads[i] = rt_thread_create(thread_fun, (void *) i, 0)))
>> {
>>                           printf("ERROR IN CREATING THREAD.\n.");
>>                           exit(1);
>>                       }
>>                   }
>>
>>                   for(i=0; i<NTASKS; i++) {
>>                       rt_thread_join(threads[i]);
>>                   }
>>
>>                   // cleanup
>>                   rt_sem_delete(barrier);
>>
>>                   if(!hard_timer_running)
>>                       stop_rt_timer();
>>
>>                   rt_make_soft_real_time();
>>                   rt_task_delete(mainTask);
>>
>>                   return 0;
>>               }
>>
>> When I compile and execute the above code, the "Ooops"-line is printed for
>> the first NTASK-1 running tasks (which means that the task keeps on
>> running with its new low priority). Is something wrong with the example or
>> with my RTAI system? Or is this just the intended behaviour of
>> rt_change_prio?
>> If I add a rt_sleep(0) after the rt_change_prio call, then this example is
>> working. In general, I think this is not an option, because I think this
>> call could also cause a task with really lower priority to run (if there
>> were no other with the same priority), couldn't it?
>> If I don't enter hard realtime, then the behaviour is the same, but the
>> "trick" with rt_sleep(0) is not even working.
>>
>>
>> Thanks in advance
>> Matthias
>> _______________________________________________
>> Rtai mailing list
>> Rtai at rtai.org
>> https://mail.rtai.org/cgi-bin/mailman/listinfo/rtai
>>
> 
> 
> 
> 



More information about the Rtai mailing list