autoconf: Volatile Objects

1 
1 13.6 Volatile Objects
1 =====================
1 
1 The keyword `volatile' is often misunderstood in portable code.  Its
1 use inhibits some memory-access optimizations, but programmers often
1 wish that it had a different meaning than it actually does.
1 
1    `volatile' was designed for code that accesses special objects like
1 memory-mapped device registers whose contents spontaneously change.
1 Such code is inherently low-level, and it is difficult to specify
1 portably what `volatile' means in these cases.  The C standard says,
1 "What constitutes an access to an object that has volatile-qualified
1 type is implementation-defined," so in theory each implementation is
1 supposed to fill in the gap by documenting what `volatile' means for
1 that implementation.  In practice, though, this documentation is
1 usually absent or incomplete.
1 
1    One area of confusion is the distinction between objects defined with
1 volatile types, and volatile lvalues.  From the C standard's point of
1 view, an object defined with a volatile type has externally visible
1 behavior.  You can think of such objects as having little oscilloscope
1 probes attached to them, so that the user can observe some properties of
1 accesses to them, just as the user can observe data written to output
1 files.  However, the standard does not make it clear whether users can
1 observe accesses by volatile lvalues to ordinary objects.  For example:
1 
1      /* Declare and access a volatile object.
1         Accesses to X are "visible" to users.  */
1      static int volatile x;
1      x = 1;
1 
1      /* Access two ordinary objects via a volatile lvalue.
1         It's not clear whether accesses to *P are "visible".  */
1      int y;
1      int *z = malloc (sizeof (int));
1      int volatile *p;
1      p = &y;
1      *p = 1;
1      p = z;
1      *p = 1;
1 
1    Programmers often wish that `volatile' meant "Perform the memory
1 access here and now, without merging several memory accesses, without
1 changing the memory word size, and without reordering."  But the C
1 standard does not require this.  For objects defined with a volatile
1 type, accesses must be done before the next sequence point; but
1 otherwise merging, reordering, and word-size change is allowed.  Worse,
1 it is not clear from the standard whether volatile lvalues provide more
1 guarantees in general than nonvolatile lvalues, if the underlying
1 objects are ordinary.
1 
1    Even when accessing objects defined with a volatile type, the C
1 standard allows only extremely limited signal handlers: the behavior is
1 undefined if a signal handler reads any nonlocal object, or writes to
1 any nonlocal object whose type is not `sig_atomic_t volatile', or calls
1 any standard library function other than `abort', `signal', and (if C99)
1 `_Exit'.  Hence C compilers need not worry about a signal handler
1 disturbing ordinary computation, unless the computation accesses a
1 `sig_atomic_t volatile' lvalue that is not a local variable.  (There is
1 an obscure exception for accesses via a pointer to a volatile
1 character, since it may point into part of a `sig_atomic_t volatile'
1 object.)  Posix adds to the list of library functions callable from a
1 portable signal handler, but otherwise is like the C standard in this
1 area.
1 
1    Some C implementations allow memory-access optimizations within each
1 translation unit, such that actual behavior agrees with the behavior
1 required by the standard only when calling a function in some other
1 translation unit, and a signal handler acts like it was called from a
1 different translation unit.  The C standard hints that in these
1 implementations, objects referred to by signal handlers "would require
1 explicit specification of `volatile' storage, as well as other
1 implementation-defined restrictions."  But unfortunately even for this
1 special case these other restrictions are often not documented well.
1 ⇒When is a Volatile Object Accessed? (gcc)Volatiles, for some
11 restrictions imposed by GCC.  ⇒Defining Signal Handlers
 (libc)Defining Handlers, for some restrictions imposed by the GNU C
1 library.  Restrictions differ on other platforms.
1 
1    If possible, it is best to use a signal handler that fits within the
1 limits imposed by the C and Posix standards.
1 
1    If this is not practical, you can try the following rules of thumb.
1 A signal handler should access only volatile lvalues, preferably lvalues
1 that refer to objects defined with a volatile type, and should not
1 assume that the accessed objects have an internally consistent state if
1 they are larger than a machine word.  Furthermore, installers should
1 employ compilers and compiler options that are commonly used for
1 building operating system kernels, because kernels often need more from
1 `volatile' than the C Standard requires, and installers who compile an
1 application in a similar environment can sometimes benefit from the
1 extra constraints imposed by kernels on compilers.  Admittedly we are
1 handwaving somewhat here, as there are few guarantees in this area; the
1 rules of thumb may help to fix some bugs but there is a good chance
1 that they will not fix them all.
1 
1    For `volatile', C++ has the same problems that C does.
1 Multithreaded applications have even more problems with `volatile', but
1 they are beyond the scope of this section.
1 
1    The bottom line is that using `volatile' typically hurts performance
1 but should not hurt correctness.  In some cases its use does help
1 correctness, but these cases are often so poorly understood that all
1 too often adding `volatile' to a data structure merely alleviates some
1 symptoms of a bug while not fixing the bug in general.
1