[En-Nut-Discussion] Not fixed!!!: Re: confirmed!!! Re: NutOS 4.4.0 on ARM7: possibly bug in NutEnterCritical / NutExitCritical

Nathan Moore nategoose at gmail.com
Fri Feb 22 19:31:04 CET 2008


Hey Matthias,

Maybe my assumptions are wrong:
> - NutEnterCritical/NutExitCritical guard short sections of code which
> run with IRQs disabled
> - These are normally just a few lines to block IRQs minimally

That's how they are supposed to be used, but not always.  Just look in the
message passing
code (which I believe to be broken).

>
> - They normally don't call other functions.

That's a good idea, but not how things are always done.

>
> - Even if they call other functions, those return and the ExitCritical
> is in the same context as the entry.

Not if you pass arguments.  The compiler may use the stack to save local
variables that are in registers  or may pass some variables on the stack.
Say you did:
   NutEnterCritical();
   A = value_that_isr_can_change;
   NutExitCritical();
   printf("%i", A);
Since A will end up on the stack anyway (all the variable length argument
list arguments are always put on
the stack) the compiler may put it there initially within the critical
section which will break stuff since A will
end up being used as the value NutExitCritical uses to restore the
interrupts.  printf will then print the interrupt
state that was supposed to be restored if printf works with interrupts off.

>
> - The stack pointer points to free space after the local (stack based)
> variables. You can push/pop stuff there
> as long as the pointer is correct before you exit.

The compiler assumes that you aren't messing with the stack directly or it
you are you are doing stuff to it and
then restoring all within one asm(...).

>
> - If you call another function, the parameters are pushed on the
> stack, the call executed and the functions returns. an eventually
> stored ISR is still safe on the stack.

Again, if compilers really understood what NutEnterCritical and
NutExitCritical did and could adjust their offsets
into the stack this would work, and it often does work anyway, but not
always.

>
>
> >> had wondered about this on AVR, which is what we are using. A
> > wonderful way to ruin everything would be to use alloca( ) within a
> > critical section.
> But. First, calling an indeterministic function (in terms of running
> time) from within an IRQ is a no-no, which must not be done.
> Second, people writing IRQ-Handler should know why they did call
> NutEnterCritical in the first place.

IRQ handlers aren't supposed to be calling enter/exit critical since they
are already in the critical state.
alloca( ) is not an indeterministic function.  All it does is tell the
compiler
that you want to allocate more space on the stack and give you a pointer
to that.  No actual function calls are made in most implementations, as it
is a compiler intrinsic.  When using alloca() the compiler is able to deal
with changing the stack pointer because it knows exactly how the stack
is being changed, but it usually does have to use more register space to
keep track of what it's doing.

>
>
> The point about NutJumpCritical is there, but I think in most cases
> the code can be reformulated to avoid it.

I agree w/ this.

Nathan



More information about the En-Nut-Discussion mailing list