[En-Nut-Discussion] RTOS Comparison
Harald Kipp
harald.kipp at egnite.de
Mon Mar 22 14:23:46 CET 2010
Hi Nathan,
Nathan Moore wrote:
> If I recall correctly the entire timer list is walked every time the
> scheduler is called.
Which code do you mean? AFAIK, the timer list _is_ a sorted list, at
least since version4, may be earlier.
The related function is NutTimerProcessElapsed(). The loop is
while (nutTimerList && ticks_new) {
}
ticks_new contains the number of ticks elapsed since the last context
switch. If the ticks_left counter of the timer on top is larger, is
reduced by ticks_new and loop is exited. Otherwise the next timer is
processed until the summed up ticks_left counters reach ticks_new.
In other words, only the first and all elapsed timers are processed.
> Every time an even was posted and a thread was waiting the
> thread would be taken off the top of the eventqueue ( O(1) operation) pushed
> onto this stack ( O(1) operation). This would be the same in ISRs and in
> applications.
> NutEventPost( void * event) {
> NutEnterCritical();
> NutPostEventFromISR(event, -1); // The second param is what to put
> on the event queue if it is empty
> NutExitCritical();
> }
> NutEventPostNext( void * event) {
> NutEnterCritical();
> NutPostEventFromISR(event, NULL);
> NutExitCritical();
> }
> NutPostEventFromISR is just a pop from the event waiting queue and a push
> to a stack.
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?
#define NutEventPostFromIrq(qp) \
{ \
if (*qp == 0) { \
*qp = SIGNALED; \
} \
else if (*qp != SIGNALED) { \
NUTTHREADINFO *tp = (NUTTHREADINFO *)(*qp); \
tp->td_qpec++; \
} \
}
On ARM this requires a few cycles only:
; Load the queue pointer
ldr r2, qp
; Load the first entry
ldr r3, [r2, #0]
; Compare with NULL
cmp r3, #0
; If NULL, set to SIGNALED and exit
mvneq r3, #0
streq r3, [r2, #0]
bxeq lr
; Otherwise compare with SIGNALED
cmn r3, #1
; If not equal, increment the qpec counter
ldrne r2, [r3, #8]
addne r2, r2, #1
strne r2, [r3, #8]
; exit
bx lr
Michael tested context switching, which is not that important for a
cooperative system like Nut/OS. But interrupt latency is most important,
because interrupts are the real-time component in Nut/OS.
Anyway, I'm sure it could be done better, preferably without increasing
interrupt latency. And you are definitely right, that walking through
the list of all threads to look for previous events is not a good
solution. Even if Michael didn't test any dependencies on the total
number of running threads (hint! hint!).
Harald
More information about the En-Nut-Discussion
mailing list