Edwin Olson schrieb:
I'm working with a small embedded O/S on an ARM7TDMI.
A typical IRQ handler must save the state of a previous task, perform
some processing, possibly invoke the scheduler, and then restore a new
task. I'd like to do as much of this as possible from C, but
automatically generated prologue/epilogue chunks interfere with my
IRQ_TASK_SAVE/RESTORE macros (which are inline assembly). So I've been
doing this:
static void emac_irq(void) __attribute__ ((naked));
static void emac_irq(void)
{
IRQ_TASK_SAVE;
emac_irq_real();
IRQ_TASK_RESTORE;
}
Calling out to the actual ISR as a separate function call seems to
isolate stack variable allocations to the section between the
IRQ_TASK_SAVE/RESTORE.
This works pretty well, however, if I optimize at -O4, emac_irq_real is
inlined, and the IRQ handler no longer runs correctly. (I've verified:
the code works with -O4 -fno-inline, but doesn't work with just -O4).
I can attach a "noinline" attribute to emac_irq_real, which again causes
things to work, but the whole thing is starting to feel clumsy.
Does anyone have an idea of how I can do this in a more elegant way,
that doesn't require setting a bunch of attributes?
What would you consider a more elegant way than being able to specify it on
function level?
The point is that, from the viewpoint of C/C++ language semantics, there is
just no difference between an inlined and a non-inlined function call.
Hence, the compiler is free to do what ever he considers best.
I strongly recommend to specify always_inline and noinline *whenever* the
resulting machine code is constrained to the one or other. That is the
exact purpose of these attributes and the only way you can achieve defined
semantics regardless of gcc version, target platform and moon phase.
(Unfortunately gcc does not inline, even not function marked as
always_inline, when compiling with -O0. This is an anachronism you can,
however, simply work around with -O1 or -finline-functions)
Daniel