Skip site navigation (1)Skip section navigation (2)
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>