avr-libc-dev
[Top][All Lists]
Advanced

[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.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]