Messages in this thread |  | | Date | Thu, 2 May 1996 14:40:18 -0700 | From | Tom May <> | Subject | Re: Is clobber "memory" in include/asm-i386/system.h necessary? |
| |
Linus Torvalds <torvalds@cs.Helsinki.FI> writes:
>Right after this I have to mention a few exceptions to the rule: there _are_ >two circumstances where using "volatile" is acceptable. > > 1) for a clock. Look at "jiffies". The whole _idea_ with a clock is that it > changes, and it's _ok_. A clock is not a linked list or anything like that. > 2) For accessing hardware registers internally. No kernel code should do it > (they should use "readb()" etc that should take care of it), but in that > context it's ok. Again, for the same reason as in (1) - it's not a data > structure, it's just a very special "value".
volatile isn't even good enough for accessing hardware registers in a portable way. It's sort of just like saying "please please please do the right thing", which doesn't always work because "the right thing" is not defined and compilers are free to do things that are "volatile" but still not quite what you had in mind. Here are two things I have seen go wrong when using various compilers:
1. "if (*(volatile long *)p & 1)" ... compiling to use "testb $1,(p)", i.e., using a byte access instead of a long, which fails if your hardware doesn't support byte accesses.
2. "*(volatile long *)p = constant" compiling (on a 16-bit compiler) to
movw $(constant >> 16),(p+2) movw $(constant & 0xFFFF),(p)
where in my case the hardware accepted word writes, but the hi/lo order broke the code because it changed the semantics.
Sure, in Linux we can probably get away with using gcc's volatile implementation for accessing hardware registers, but it's still a good idea to make sure it "does the right thing" (which it does, for now).
As an aside, gcc's implementation of volatile at the RTL level will not allow its instruction combiner to generate code like in case 1. It's lousy code generation when confronted with "volatile" is a result of breaking down each source expression into RISC-like steps called RTL insns, then trying to combine them later, e.g., doing the RTL equivalent of combining "movl (p),%reg" with "testl $1,%reg" to get "testl $1,(p)". The problem is that RTL insns which were generated from volatile expressions are not subject to instruction combination. This could possibly be fixed by adding another field to each RTL insn that says what source expression generated it, and allowing volatile RTL insns to be combined if they were generated from the source expression.
Tom.
|  |