EmbeddedRelated.com
Forums
Memfault State of IoT Report

"asm volatile" and GCC

Started by Graeme Prentice March 22, 2004

Using G++ (i.e. C++) for a Hitachi H8S micro, if we have inline
functions to enable and disable interrupts using asm volatile like this

inline void EnableInterrupts(void)  {
  asm volatile("andc #0x3f,ccr" : : : "cc", "memory" );
}
inline void DisableInterrupts(void)  {
  asm volatile("orc #0xc0,ccr"  : : : "cc", "memory" );
}

does this mean that we can assume that all reads/ writes / function
calls etc that appear in the source code "logically" between an
EnableInterrupts and DisableInterrupts will be done with interrupts
disabled even if the variables being accessed are not themselves
volatile e.g.

	DisableInterrupts();
	print( somevar );
	EnableInterrupts();

Can the compiler read somevar before disabling interrupts, for example.

The GCC manual says using "asm volatile" prevents the asm instruction
from being "moved significantly" and adding "memory" to the clobber list
prevents GCC from keeping memory values cached in registers across the
assembler instruction, but also says "GCC will perform some
optimizations across a volatile asm instruction" but doesn't explain
what.

Is the above code safe or should we make enable / disable interrupts do
calls to hidden functions?

Graeme
"Graeme Prentice" <invalid@yahoo.co.nz> wrote in message
news:jnjt505l07fcd4gsrm382t6o9q0atk3que@4ax.com...
> > > Using G++ (i.e. C++) for a Hitachi H8S micro, if we have inline > functions to enable and disable interrupts using asm volatile like this > > inline void EnableInterrupts(void) { > asm volatile("andc #0x3f,ccr" : : : "cc", "memory" ); > } > inline void DisableInterrupts(void) { > asm volatile("orc #0xc0,ccr" : : : "cc", "memory" ); > } > > does this mean that we can assume that all reads/ writes / function > calls etc that appear in the source code "logically" between an > EnableInterrupts and DisableInterrupts will be done with interrupts > disabled even if the variables being accessed are not themselves > volatile e.g. > > DisableInterrupts(); > print( somevar ); > EnableInterrupts(); > > Can the compiler read somevar before disabling interrupts, for example. > > The GCC manual says using "asm volatile" prevents the asm instruction > from being "moved significantly" and adding "memory" to the clobber list > prevents GCC from keeping memory values cached in registers across the > assembler instruction, but also says "GCC will perform some > optimizations across a volatile asm instruction" but doesn't explain > what. > > Is the above code safe or should we make enable / disable interrupts do > calls to hidden functions?
Hi, I'm not that familiar with Hitachi H8S Architecture. However, as far as "code-safety" you might consider disabling and enabling interrupts that in this way: InterruptMaskState state; /* on stack */ DisableInterrupts ( &state ); /* save current interrupt state and disable interrupts */ /* critical work ... */ RestoreInterrupts ( &state ); /* restore the state of the interrupts */ This way you can make nested or re-entrant calls to your functions without having to worry about what might me undesirable behavior. Also, "volatile" in GCC is the same as disabling compiler optimizations for that specific variable. I suggest that you make some small, easily to validate examples with and without the "volatile" keyword and look at what the compiler outputs. -Bryan
On Mon, 22 Mar 2004 21:05:53 GMT, Bryan Bullard wrote:

> >Hi, I'm not that familiar with Hitachi H8S Architecture. However, as far as >"code-safety" you might consider disabling and enabling interrupts that in >this way: > >InterruptMaskState state; /* on stack */ > >DisableInterrupts ( &state ); /* save current interrupt state and disable >interrupts */ > >/* critical work ... */ > >RestoreInterrupts ( &state ); /* restore the state of the interrupts */ > >This way you can make nested or re-entrant calls to your functions without >having to worry about what might me undesirable behavior.
Yep, we have something similar to this (but using constructor/ destructor) as well as plain enable / disable.
> >Also, "volatile" in GCC is the same as disabling compiler optimizations for >that specific variable. I suggest that you make some small, easily to >validate examples with and without the "volatile" keyword and look at what >the compiler outputs.
We really need a guarantee that it will work correctly for all cases. We know what the guarantee for volatile variables is but "asm volatile" is not quite the same as a volatile variable. Thanks for the reply. Graeme
"Graeme Prentice" <invalid@yahoo.co.nz> wrote in message
news:gla060ltgiu8m6lsg2f8qu0phij11kb4um@4ax.com...
> On Mon, 22 Mar 2004 21:05:53 GMT, Bryan Bullard wrote:
> >Also, "volatile" in GCC is the same as disabling compiler optimizations
for
> >that specific variable. I suggest that you make some small, easily to > >validate examples with and without the "volatile" keyword and look at
what
> >the compiler outputs. > > We really need a guarantee that it will work correctly for all cases. > We know what the guarantee for volatile variables is but "asm volatile" > is not quite the same as a volatile variable.
If you are worried about what the compiler will do with consecutive "asm volatile" statements don't do it. Use a single "asm" statement. If it's that vital than you're going to want to validate everything compiler emits anyway.
>"Bryan Bullard" <reply@to.group.com> wrote in message news:<RyI7c.9563> >Also, "volatile" in GCC is the same as disabling compiler optimizations for > that specific variable. I suggest that you make some small, easily to > validate examples with and without the "volatile" keyword and look at what > the compiler outputs.
The empirical answer is that you do need the volatile key word AS WELL as the "cc" AND "memory" clobber-modifiers. I wish I can say that I discovered this by creating a small test/example program, but I did it the old fashion way of chasing down a race condition in a real life application :(.
Graeme Prentice <invalid@yahoo.co.nz> wrote:
> We really need a guarantee that it will work correctly for all cases.
Odds are you won't get one about GCC, ever, from anyone. As the GPL puts it: NO WARRANTY. None, whatsoever, of any kind. If you want a guarantee, you'll have to check the source (and trust GCC itself to translate that into exactly the behaviour expressed by the source says...). Or at least, if you want to ask someone about it, ask the GCC people themselves, not this newsgroup. That said, I'll second the recommendation given by someone else already: if you absolutely have to be sure, code the entire critical section in assembly, period. -- Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de) Even if all the snow were burnt, ashes would remain.
"John Taylor" <jtaylor@shift-right.com> wrote in message
news:4cf5cdf1.0403231817.203e7e6c@posting.google.com...
> >"Bryan Bullard" <reply@to.group.com> wrote in message news:<RyI7c.9563 > >Also, "volatile" in GCC is the same as disabling compiler optimizations
for
> > that specific variable. I suggest that you make some small, easily to > > validate examples with and without the "volatile" keyword and look at
what
> > the compiler outputs. > The empirical answer is that you do need the volatile key word AS WELL > as the "cc" AND "memory" clobber-modifiers. > > I wish I can say that I discovered this by creating a small > test/example program, but I did it the old fashion way of chasing down > a race condition in a real life application :(.
That can shorten your life you know.
On 24 Mar 2004 13:43:56 GMT, Hans-Bernhard Broeker wrote:

>Graeme Prentice <invalid@yahoo.co.nz> wrote: >> We really need a guarantee that it will work correctly for all cases. > >Odds are you won't get one about GCC, ever, from anyone. As the GPL >puts it: NO WARRANTY. None, whatsoever, of any kind.
When I said guarantee, I meant "the intended behaviour of the compiler", for which GCC has a large manual. I was looking for confirmation of my interpretation of it.
> >If you want a guarantee, you'll have to check the source (and trust >GCC itself to translate that into exactly the behaviour expressed by >the source says...).
I didn't think of that. Thanks.
> Or at least, if you want to ask someone about >it, ask the GCC people themselves, not this newsgroup.
I did. There was no response. The linux kernel uses asm volatile / "memory" extensively so I think people on the linux.kernel newsgroup would know plenty about it but I don't like to ask on that ng because it's extremely busy and my question would be slightly OT.
> >That said, I'll second the recommendation given by someone else >already: if you absolutely have to be sure, code the entire critical >section in assembly, period.
We could make enable/disable call a "hidden" function (it can't see the definition) and then the compiler would be forced to inhibit optimisations/caching/reordering across the function calls. This would be enough of a guarantee because we know that large amounts of code already depend on the compiler handling calls to hidden functions correctly i.e. this feature of the compiler has been extremely well tested. Using asm volatile allows us to slightly shorten the time that interrupts are disabled for. Graeme
Graeme Prentice wrote:

>>Odds are you won't get one about GCC, ever, from anyone. As the GPL >>puts it: NO WARRANTY. None, whatsoever, of any kind. >
Which differs from commercial compilers in that THEIR declaration that it is not guaranteed to do anything in particular is well hidden in the legalese of the licensing agreement. Do you know of ANY compiler that carries a guarantee of correct behaviour under all circumstances? Paul Burke
On Thu, 25 Mar 2004 08:31:26 +0000, Paul Burke wrote:

>Graeme Prentice wrote: > >>>Odds are you won't get one about GCC, ever, from anyone. As the GPL >>>puts it: NO WARRANTY. None, whatsoever, of any kind. >>
I didn't write this. Graeme

Memfault State of IoT Report