> What code is sending the packets and how are they received (I mean user
> space application, or some kernel code?)

Most of the network traffic is incoming (99.99...%). There is a server
application (in user space) that receives the data and stores it in
the shared memory, accessible to RT tasks for processing.

> I guess you should somehow allow network interrupt to be serviced while
> your RT task is running. How much time is your RT task taking?

That was my idea. I modified the rate-monotonic scheduler (the
original is available on the RTL web page), so that rt_linux_task (the
Linux kernel) is assigned a period, just like the RT tasks. For a
start, I set this period to 20ms, while the RT tasks had periods of
50ms and 500ms (two sets of them, currently). Each time the
rt_linux_task preempts another task, I set the timer to call
rt_schedule() after, say, 2ms (it is possible that some delayed RT
task has sooner resume_time, so that the 2ms is the upper bound of
time that rt_linux_task has available). When the following call to
rt_schedule() is made, rt_linux_task is made delayed (from ready), so
that the RT tasks can continue to run. This idea seems to work for
some values of the period and "demand"... I am attaching chunks of the
modified code (look for "AMB") in rt_monotonic_sched.c; I admit I am
not 100% sure about the interrupt and flag "fix".

> Tomek

Thanks!
Aleks

void 
rt_schedule(void)
{
        RTIME now;
        RTIME preemption_time;
        RT_TASK *task;
        RT_TASK *new_task;
        RT_TASK *preemptor;
        RTIME   shortest_period;

        int flags, flags2; /* AMB */

        r_save_flags(flags);
        save_flags(flags2); /* AMB */
        r_cli();
        cli(); /* AMB */

        now = rt_get_time(); /* moved up by AMB */
#ifdef DEBUG
        if (rt_current->identifier != -1) {
            debug.state = EXEC;
            debug.id    = rt_current->identifier;
            debug.in    = init_time;
            debug.out   = now;
            rtf_put(DEBUG_FIFO, (char *) &debug,  sizeof(debug));
        }
#endif  

        for (task = rt_tasks; task; task = task->next)
          {
            if (task->state == RT_TASK_DELAYED && 
                task->resume_time < (now+10))
              {
                task->state = RT_TASK_READY;
              }
          }
        new_task = 0; /* &rt_linux_task; AMB */

/* begin rate-monotonic scheduling    */
        shortest_period = RT_BIGGEST_PERIOD; /* rt_linux_task.period; AMB */

        /* AMB begin */
        if ((rt_current == &rt_linux_task) &&
            (rt_linux_task.priority == RT_LOWEST_PRIORITY))
          {
            rt_linux_task.state = RT_TASK_DELAYED;
            rt_linux_task.priority = RT_LOWEST_PRIORITY - 1;
            rt_linux_task.resume_time += rt_linux_task.period;
          }
        /* AMB end */
      
        for (task = rt_tasks; task; task = task->next)
          {
            if (task->state == RT_TASK_READY && 
                task->period < shortest_period)
              {
                new_task = task;
                shortest_period = task->period;
              }
          }

        preemptor = 0;
        preemption_time = RT_TIME_END;
        /* AMB begin */
        if (new_task == &rt_linux_task)
          {
            rt_linux_task.priority = RT_LOWEST_PRIORITY;
            preemptor = &rt_linux_task;
            preemption_time = now + RT_TICKS_PER_SEC / 100;
          }
        /* AMB end */
        for (task = rt_tasks; task; task = task->next)
          {
            if (task->state == RT_TASK_DELAYED && 
                task->resume_time < preemption_time)
              {
                preemption_time = task->resume_time;
                preemptor = task;
              }
          }

        /* AMB begin */
        if (new_task == 0)
          {
            rt_linux_task.state = RT_TASK_READY;
            rt_linux_task.priority = RT_LOWEST_PRIORITY - 2;
            new_task = &rt_linux_task;
          }
        /* AMB end */

/* End of rate-monotonic scheduler */

        if (preemptor)
          {
            rt_set_timer(preemption_time);
          }
        else
          {
            rt_no_timer();
          }
        
        if (new_task == rt_current)
          {
            if (rt_current != &rt_linux_task)
              rt_current->resume_time += rt_current->period; /* AMB */
            r_restore_flags(flags);
            restore_flags(flags2); /* AMB */
            return;
          }

        if (new_task == &rt_linux_task)
          {
            SFIF = linux_irq_state;
          }
        else
          if (rt_current == &rt_linux_task)
            {
              linux_irq_state = SFIF;
              SFIF = 0;
            }

#ifdef DEBUG
        if (new_task->identifier != -1) {       /* Monotonic scheduler */
                init_time = now;
        }
#endif

        new_task->state = RT_TASK_READY;
        rt_switch_to(new_task);
        r_restore_flags(flags);
        restore_flags(flags2); /* AMB */
}

int 
init_module(void)
{
#ifdef DEBUG
        rtf_create(DEBUG_FIFO, 4000);
#endif
        rt_tasks = &rt_linux_task;
        rt_current = &rt_linux_task;
        rt_linux_task.priority = RT_LOWEST_PRIORITY - 1; /* AMB */
        rt_linux_task.period   = RT_TICKS_PER_SEC / 50; /* RT_BIGGEST_PERIOD; AMB */
        rt_linux_task.resume_time = rt_get_time(); /* AMB */
        rt_linux_task.next = 0;
        rt_linux_task.identifier = -1; /* Monotonic */
        rt_linux_task.state = RT_TASK_READY;
        rt_request_timer(&rt_schedule);
        return 0;
}
--- [rtl] ---
To unsubscribe:
echo "unsubscribe rtl" | mail [EMAIL PROTECTED] OR
echo "unsubscribe rtl <Your_email>" | mail [EMAIL PROTECTED]
----
For more information on Real-Time Linux see:
http://www.rtlinux.org/~rtlinux/

Reply via email to