Date: Wed, 12 Jan 2000 21:34:12 -0500 From: "Mikhail Evstiounin" <evstiounin@adelphia.net> To: <keramida@ceid.upatras.gr>, "Laurence Berland" <stuyman@confusion.net> Cc: <freebsd-questions@FreeBSD.ORG> Subject: Re: Volatile variables (was: Giving a sighandler more information) Message-ID: <001601bf5d6e$b2ac8660$fc353018@evstiouninadelphia.net.pit.adelphia.net>
index | next in thread | raw e-mail
-----Original Message-----
From: Giorgos Keramidas <charon@hades.hell.gr>
To: Laurence Berland <stuyman@confusion.net>
Cc: freebsd-questions@FreeBSD.ORG <freebsd-questions@FreeBSD.ORG>
Date: Wednesday, January 12, 2000 9:23 AM
Subject: Volatile variables (was: Giving a sighandler more information)
>On Tue, Jan 11, 2000 at 06:54:47PM -0500, Laurence Berland wrote:
>>
>>
>> Oliver Fromme wrote:
>> >
>> > Laurence Berland <stuyman@confusion.net> wrote in
list.freebsd-questions:
>> > > Oliver Fromme wrote:
>> > >>
>> > >> I'm afraid there is no other way than using global variables.
>> > >> Be sure to declare them as ``volatile sig_atomic_t''.
>> > >>
>> > > What does this do as compared to declaring them normally?
>> >
>> > It makes them work, as opposed to not work. :-)
>> >
>> > Seriously. You _must_ declare global variables which are
>> > accessed from a signal handler as ``volatile sig_atomic_t''.
>> > Everything else is _not_ guaranteed to work (and if it works,
>> > then it's just pure luck).
>> >
>> > Regards
>> > Oliver
>> >
>>
>> Does this have something to do with the signal being caught while
>> we're in the signal routine? Am I on the right track?
>
>Almost. AFAIK, when you use `volatile' each time the variable is
>referenced, the compiler will generate a memory reference, not relying
>on the value being saved in a register, etc. The same if true for when
>the variable is `written', i.e. the memory copy is kept up to date.
>
>For the simple program:
>
> volatile int k;
>
> int main (void)
> {
> k = 0;
> k = 1;
> return 0;
> }
>
>the command `cc -S' will generate the following (slightly edited)
>assembler code. The comments are there to help you understand which
>lines of the assembler code correspond to C code.
>
> .text
> .p2align 2
> .globl main
> .type main,@function
> main:
> pushl %ebp /* { */
> movl %esp,%ebp
>
> movl $0,k /* k = 0; */
>
> movl k,%eax /* k = 1; */
> incl %eax
Oliver, first of all, this is optimization already nad compiler tries to
keep value in register to have fast access to the value. I told that this is
optimization
you used I386 commands and I386 has increment in memory. If you want to turn
optimization completely it should look like this
incl k
Remember, that k is global and located in a special segment. Take a look at
my quote
- in another e-mail - A volatile specifier is a hint to a compiler that an
object may change
its value in ways not specified by the language.
That's it, a compiler will try to keep everything in memory, no assumption
about registers.
And a timer is a good example when "foreign" force can change the value of
timer - not
a program. BTW, it's a good rool for global variables - do not optimize too
much - a
value could be change in procedure, allocated in another compilation unit
and compiler
has zero knolwledge about this "another" compilation unit. This is
especially true in
C++ world. A global variable could be changed even you do not have explicit
calls
of another functions - block try-catch creates a dynamic frame and all other
functions
called from inside try block are working inside this frame - any problem and
control
goes to the catch block and this block could change the variable.
Declaring vilotile in this particular case doesn't help a lot - you could
get a signal
between incl eax and movl %eax,k - and you are done - value in register
doesn't correspond to the value in memory. Moreover, if you change global
variable in
your signal handler, this value will be lost after movl %eax,k command. What
it's important is that these two operation should be atomic ones. In other
words,
incl k could not be interrupted, or you should provide uninterruptable
sequence of
command and, I believe, sig_atomic_t does it.
> movl %eax,k
>
> xorl %eax,%eax /* return 0; */
>
> leave /* } */
> ret
> .Lfe1:
> .size main,.Lfe1-main
> .comm k,4,4 /* volatile int k; */
>
>You can see that although %eax is used as an intermediate register for
>increasing the C variable called `k', the value of %eax is saved to the
>memory location of `k' before the end of the k = 1; statement.
>
>This is exactly what volatile means. The memory value is always
>updated to reflect changes to the value of every volatile identifier.
>
Like I told above it should be done in atomic way, but vilotale means -
avoid
optimiozations. And again it's a hint - just a hint. Some aggresive
optimizers
could ignore it. For example, if commands cli/sti could be used by compiler
and works like it work in 8086, optimizer could do the following:
volatile int k;
int main (void)
{
int m = 4;
k = 0;
k = 1;
m = k;
return 0;
}
pushl %ebp /* { */
movl %esp,%ebp
mov %edx,4 - compiler was able to figure out that it could
allocate variable in reg.
cli
xor %eax,%eax
movl %eax,k /* k = 0; */
incl %eax - k =1
movl %eax,%edx - m =k;
movl %eax,k - synchronize k
sti
xorl %eax,%eax /* return 0; */
leave /* } */
ret
.Lfe1:
.size main,.Lfe1-main
.comm k,4,4 /* volatile int k; */
>--
>Giorgos Keramidas, < keramida @ ceid . upatras . gr >
>"What we have to learn to do, we learn by doing." [Aristotle]
>
>
>To Unsubscribe: send mail to majordomo@FreeBSD.org
>with "unsubscribe freebsd-questions" in the body of the message
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-questions" in the body of the message
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?001601bf5d6e$b2ac8660$fc353018>
