[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-libc-dev] "cli" and "sei" should clobber memory
From: |
Paulo Marques |
Subject: |
Re: [avr-libc-dev] "cli" and "sei" should clobber memory |
Date: |
Tue, 13 Dec 2005 02:21:35 +0000 |
User-agent: |
Internet Messaging Program (IMP) H3 (4.0.4) |
Quoting Eric Weddington <address@hidden>:
Joerg Wunsch wrote:
Sure, the memory clobber causes something like a "global volatile"
effective for *all* memory variables at these sequence points. IOW,
it's a huge pessimization, and (IMHO) *way* worse than declaring your
single variable to be volatile, and shadow its value where the
volatileness isn't needed.
IMHO, I don't think it is *way* worse. Just take this example, a simple
interrupt routine that does this:
my_var++;
if (my_var == 100)
my_var = 0;
Where my_var is simply an unsigned int.
If I declare it volatile the assembly grows like this:
my_var++;
6a: 80 91 60 00 lds r24, 0x0060
6e: 90 91 61 00 lds r25, 0x0061
72: 01 96 adiw r24, 0x01 ; 1
74: 90 93 61 00 sts 0x0061, r25
78: 80 93 60 00 sts 0x0060, r24
if (my_var == 100)
7c: 80 91 60 00 lds r24, 0x0060
80: 90 91 61 00 lds r25, 0x0061
84: 84 36 cpi r24, 0x64 ; 100
86: 91 05 cpc r25, r1
88: 21 f4 brne .+8 ; 0x92 <__vector_8+0x36>
my_var = 0;
8a: 10 92 61 00 sts 0x0061, r1
8e: 10 92 60 00 sts 0x0060, r1
Those 2 extra loads are 4 extra cycles inside my high frequency
interrupt function where the volatile shouldn't be needed at all. And
this is the simplest example I could think of.
Even more, the memory clobber only affects "memory", i.e., stuff that
the compiler keeps in memory like global vars or local vars whose
address has been taken and passed to some function. If you have local
vars kept in registers (even if these spill into memory), these won't
be affected by the memory clobber, so in many cases it is not that
expensive at all.
I know I could handle the calculations in a local var in the example
above, but the point is that turning the variable into a volatile is
also a huge pessimization, and can be even worse than the memory
clobber, depending on the actual code.
Now, the really worse part is that, IIRC, the memory clobber is
actually supposed to happen in any function call that the compiler
isn't able to inline. And even if it is able to inline it, it must be
pretty sure that the function doesn't use the variable it is
reordering, so that inlining or not, should produce the same result.
So when I "call" sei() I do expect it to clobber memory, since that is
a side effect of a function call. I don't expect the compiler to
reorder function calls around global variable assignments.
This certainly, at the very least, violates the "principle of least
surprise", because "sei();" _looks_ a lot like a function call ;)
[...]
Another possible way is to do this:
dword atomic_get_dword(volatile dword *ptr)
{
dword ret;
cli();
ret = *ptr;
sei();
return ret;
}
Untested of course.
This actually works, but is more of a workaround and doesn't solve the
"access two variables atomically" scenario.
Anyway, I just feel this is not the expected behavior of a cli/sei pair
and that there is a lot of code out there that assumes that global vars
won't be touched by an interrupt routine inside a cli/sei pair :(
--
Paulo Marques
----------------------------------------------------------------
This message was sent using IMP, the Internet Messaging Program.