Date: Mon, 17 Jan 2000 05:57:15 +0100 (CET) From: Oliver Fromme <olli@dorifer.heim3.tu-clausthal.de> To: freebsd-questions@FreeBSD.ORG Subject: Re: Volatile variables Message-ID: <200001170457.FAA88762@dorifer.heim3.tu-clausthal.de> In-Reply-To: <85rdp2$g65$1@atlantis.rz.tu-clausthal.de>
next in thread | previous in thread | raw e-mail | index | archive | help
Mikhail Evstiounin <evstiounin@adelphia.net> wrote in list.freebsd-questions: > From: Oliver Fromme <olli@dorifer.heim3.tu-clausthal.de> >>No, it's _exactly_ the same, as far as the compiler is >>concerned. The meaning of "volatile" is to prevent the >>compiler's optimizer stage from assuming that the content >>of a variable cannot change _asynchronously_ between >>C statements. The important word is ``asynchronously''. >>It means changes to variables outside of the control flow >>which is known to the compiler at compile-time. This >>includes signal handlers just as well as hardware registers, >>shared memory etc. > > Wrong, wrong and wrong. Hardware generates interrupts, > changes statues and value in hardware registers totaly async > and this process is out of your control. Delivery of a signal is, in essence, cause by a hardware interrupt, directly or indirectly. It is what you call "totally async". > Moreover, your process will be stopped as soon as > sighandler gets its control. No, the sighandler is part of the process. When a signal handler gets called, this is (simply speaking) like an asynchronous and non-foreseeable subroutine call. > This process is totally under your control No, it is not. In particular, the compiler is unable to take it into consideration during register optimization. > [useless example with race-conditions deleted] > And vilotale doesn't help a bit!!! True, volatile does not help against typical race-conditions. That's not the purpose of volatile. Volatile does not help for basic synchronization, this is the programmer's task, but not the task of volatile. Without volatile, the programmer would be _completely_ unable to use global variables within signal handlers, because the compiler could hold their values in registers for an indefinite amount of time. In theory, if the processor hardware has enough registers, _all_ variables of the whole program could be held in registers during the _whole_ lifetime of the process. There would be never a variable stored in memory. This is perfectly legal, and a programmer whould have no chance to access them from within a signal handler. Volatile is the only solution to that problem. Therefore, it is necessary, and a compiler _must_ obey it. It basically forbids register optimizations for that particular variable. > Again, I let myself to cite BS book (p. 808) - "an object can change its > value "BS book"? How about quoting from an authoritative reference? > in ways not specified by the language". In my mind, this is very careful > and strict statement. I'm sorry, but I think it's rather misleading. > Any ofthis book or article will show you how to live without > vilotile in async process environment. You cannot solve the problem without "volatile" which I've demonstrated above. The ANSI/ISO C standard is missing in your list of books. ;-) I'd recommend that you read the section about "volatile". Yet another example (simplified): extern int i; extern int j; void foo (void) { j = i * i; j += i; } Compiled with ``cc -O3 -Wall -ansi -pedantic -c'', the result is: movl i,%eax imull %eax,%eax addl j,%eax movl %eax,0x0 Note that there could be other, unrelated statements between those two, and the compiler would still be allowed to hold everything in registers, if possible. If a signal handler is called at this point, you have three problems: 1) If it reads the variable j, it gets the wrong value, because j has not been updated yet. 2) If it writes to i, the value would not be used by the function after return from the signal handler. 3) If it writes to j, the value will be ignored and overwritten after return from the signal handler. In short: The whole thing breaks without volatile. Adding "volatile" to the declaration of i and j changes the code considerably: movl i,%eax movl i,%edx imull %edx,%eax movl %eax,j movl j,%eax movl i,%edx addl %edx,%eax movl %eax,j As you can see, now the contents of i and j are always consistent. This code works fine, even when an asynchronous mechanism (signal handler, hardware, etc.) tries to access them at some point. Regards Oliver -- Oliver Fromme, Leibnizstr. 18/61, 38678 Clausthal, Germany (Info: finger userinfo:olli@dorifer.heim3.tu-clausthal.de) "In jedem Stück Kohle wartet ein Diamant auf seine Geburt" (Terry Pratchett) 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?200001170457.FAA88762>