[Rtai] Lowering the task priority doesn't work as expected
Richly, Matthias
Matthias.Richly at student.hpi.uni-potsdam.de
Fri Apr 24 12:25:06 CEST 2009
Thanks a lot for your help, but there are 2 reasons why I think this fix won't help me.
At first: The system where the rtai app should run later on is build on RTAI 3.4 and I think I can't update it. (It is delivered as is, see http://www.festo-didactic.com/int-en/learning-systems/education-and-research-robots-robotino/the-complete-robotino-package.htm)
And second: I think a rt_change_prio() followed by a (fixed) rt_task_yield() would still not do what I need. What I need is: the task with the highest priority always runs and: it is only preempted if a task with a really higher priority becomes ready. So if a task lowers its priority, it must always be inserted in front of the ready queue of its new priority. But rt_task_yield() would cause it to be appended at the end.
An example: There are several ready tasks at prio 10 and one task t at prio 5 (so this one is running). Then t lowers its priority to 10. Now it should not loose the cpu, because there are no other tasks with a higher priority. But if I would use the rt_change_prio(); (fixed) rt_task_yield(); construct, t would loose the cpu and the task which was first in the ready queue before would run.
I think I don't need rt_task_yield(), but something that causes RTAI to do a rescheduling (without any side effects).
If such a service is not accessible from user space, maybe we can find another solution. For that, I have the following questions: Is it possible to add a new service to RTAI which does the priority change as I need it? Somethink like int rt_change_my_prio(int new_priority)? Is it maybe possible to put it into a new kernel module, which is additionally loaded where it is needed? Could such a solution work for different RTAI versions (beginning from 3.4) and without having to touch any existing modules? Of course, this new service should also be made accessible from user space.
best regards
Matthias
________________________________
Von: Paolo Mantegazza [mailto:mantegazza at aero.polimi.it]
Gesendet: Fr 24.04.2009 11:06
An: Richly, Matthias
Cc: rtai at rtai.org
Betreff: Re: AW: [Rtai] Lowering the task priority doesn't work as expected
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