[En-Nut-Discussion] RTOS Comparison

Nathan Moore nategoose at gmail.com
Mon Mar 22 19:54:49 CET 2010


>
> Which code do you mean? AFAIK, the timer list _is_ a sorted list, at
> least since version4, may be earlier.
>

I really should have looked back at that code before posting.  It has
been a while since
I looked at it and I must have remembered it wrong.  I may have been
remembering some
other OS.
Sorry about that.



>
> In general I support your idea of a separate thread stack. Not sure yet,
> how it would behave in detail. Wouldn't this significantly increase
> interrupt latency, when compared to the current implementation?

It is a few more instructions in the else case, but it also allows the system
to do away with several critical sections elsewhere.
It also doesn't have any effect on the case of empty wait queue (signaled or
unsignaled) except for code size (but still, only a few instructions).
It would also get rid of the td_qpec field in the thread structure.


>
> #define NutEventPostFromIrq(qp)     \
> {                                   \
>    if (*qp == 0) {                 \
>        *qp = SIGNALED;             \
>    }                               \
>    else if (*qp != SIGNALED) {     \
>        NUTTHREADINFO *tp = (NUTTHREADINFO *)(*qp);    \
>        /*tp->td_qpec++;*/              \
             *qp = tp->td_qnext;  \
             NUTTHREADINFO *eq = EventQueue; \
             *tp->td_qnext = eq; \
             EventQueue = tp; \
>    }                               \
> }
>



> Michael tested context switching, which is not that important for a
> cooperative system like Nut/OS.
Did he test just context switching or the entire schedule?
If it's just context switching then it's hard to improve without
figuring out which registers are dead at the time of switching and not
spending more time doing that than you'd save.  The compliment to this
is even more tricky, but this is something that you sort of get when
you use protothreads.

>But interrupt latency is most important,
> because interrupts are the real-time component in Nut/OS.

Temporarily ignoring queued up interrupts (ie uart1 receives a byte
while uart0's isr is still processing), that doesn't really matter
with respect to response latency.
The response time includes the ISR time + the time it takes to switch
to a thread that can handle the new condition, unless the condition is
handled entirely in the ISR in which case there is no need to post the
event at the end.

Now, when interrupts may become queued up you also have to consider
the various cricical sections in the rest of code as well as ISRs
because they both hold off new interrupts.  If you can remove lots of
critical sections by adding a few more instructions to ISRs I think
you have benifited.
If the amount of time added to the ISRs was more, the same, or even
just close to the amount of critical section time being spent in
NutThreadResume looking for ISR posted events which may or may not
have happened.
By using the event stack you only really have to do extra work for
real events rather than treating every thread as a possible ISR posted
event, and less of the overall work that is done has to be done with
interrupts disabled.

Of course you could just do away with the current non-ISR versions of
event posting and use incrementing of the event post counter for all
events.  This wouldn't improve the task switching behavior at all, but
would still simplify all of the other event posting stuff.  It would
also make it so that when you did walk the thread list you would be
more likely to find more posted events, which would make that work
more worth it.


On a related note, while this wouldn't really improve the amount of
time it would take for thread switching and probably wouldn't be used
a lot but is essentially free and avoids some context switches is to
create a NutThreadSetPriorityAsync.
I have used this when I knew that the thread was about to go to have
to wait on an event anyway.  It avoids some tests and a possible
context switch.  It's very useful in a few situations, such as
temporarily boosting the priority of a thread so that you can perform
some action and then wait for it's response without incurring lots of
extra latency.  This might be done around the chat script code

Something that just popped to mind that could do away with lots of
critical sections would be if NutThreadAddPriQueue/RemovePriQueue
could be passed a value to use as the new status register and use a
alternate versions of NutEnterCricital that took this value as the new
status register.  Then you could avoid actually disabling interrupts
when processing the run queue and possibly event queues for events
that aren't posted by ISRs without having to have different versions
of (or if/else stuff in) the add and remove queue code.

Nathan Moore



More information about the En-Nut-Discussion mailing list