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>
next in thread | raw e-mail | index | archive | help
-----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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?001601bf5d6e$b2ac8660$fc353018>