[En-Nut-Discussion] Fwd: Not fixed!!!: Re: confirmed!!! Re: NutOS 4.4.0 on ARM7: possibly bug in NutEnterCritical / NutExitCritical
duane ellis
ethernut at duaneellis.com
Wed Feb 27 02:21:49 CET 2008
Alain M. wrote:
>
> Duane Ellis escreveu:
>> Nathan Moore wrote:
>>> The reason you use "memory" in clobber as I understand it is if you
>>> were
>>> to alter something through a pointer within an asm operation.
>>>
>> Yes, and that is effectively what *can* *appear* to happen when IRQs are
>> re-enabled.
> Can you explain this a bit, please? I am new to ARM and relatively new
> to GCC, so I missed something and I cannot see what :)
"memory" tells the compiler that "memory is being clobbered"
Or put another way - "this is a memory barrier"
Picture Gandolf the wizard screaming at the Optimizer Beast "THOU SHALT
NOT PASS"
Less dramatically put: It is an optimization fence post or barrier.
Compile the following code snippet with "arm-elf-gcc -O2 -S foo.c",
look at the result "foo.s" file.
GCC in the UNSAFE condition optimizes the two additions into a single +2
addition.
The difference is "memory" or "not".
In this case, I am not using "volatile variables" - or am I accessing a
through a pointer.
A naive developer would think the code is safe.
The below only fails in *ARM*. It will not fail in *THUMB*.
Why? The "mrs" instruction is only ARM.
One could - construct a fancier inline asm for THUMB...
that (1) does the arm/thumb dance, (2) execute mrs, and (2) dance to thumb.
Maybe - in that case this bug would remain, I do not know.
Most often, one would instead create a small "arm/thumb" interwork
function to do the MRS instruction.
Because it would be *not*inline*asm* - the function call it self acts
like a memory barrier.
Hence, the bug report would be "works in thumb" and "fails in arm"
-Duane.
===SNIP===
#define LINUX_raw_local_irq_enable() \
({ \
unsigned long temp; \
__asm__ __volatile__( \
"mrs %0, cpsr @ local_irq_enable\n" \
" bic %0, %0, #128\n" \
" msr cpsr_c, %0" \
: "=r" (temp) \
: \
: "memory", "cc"); \
})
#define UNSAFE_raw_local_irq_enable() \
({ \
unsigned long temp; \
__asm__ __volatile__( \
"mrs %0, cpsr @ local_irq_enable\n" \
" bic %0, %0, #128\n" \
" msr cpsr_c, %0" \
: "=r" (temp) \
: : "cc" \
); \
})
int x;
int y;
void
safe_function(void)
{
x++;
LINUX_raw_local_irq_enable();
x++;
}
void
unsafe_function(void)
{
y++;
UNSAFE_raw_local_irq_enable();
y++;
}
=== SNIP ====
More information about the En-Nut-Discussion
mailing list