Volatile is stupid

Chris Torek chris at mimsy.UUCP
Tue Jun 21 11:53:41 AEST 1988


>In article <5800 at aw.sei.cmu.edu> firth at bd.sei.cmu.edu.UUCP (Robert Firth)
>writes:
>>... the compiler [could] read a single "target memory definition file",
>>or similar, that says
>>	00000000..0003ffff is ROM
>>	00040000..00ffffff is RAM
>>	fffffeeb	   is volatile
>>... Not only does this work, it is amenable to decent verification,
>>management, configuration control, and maintenance.  "Volatile" is
>>a hacker's answer.

(with which I mostly agree, although I think `hacker's answers' are not
inherently wrong.)

In article <278 at ralph.UUCP> pja at ralph.UUCP (Pete Alleman) writes:
>The compiler generally DOES NOT KNOW the address being accessed.

And why not?  The answer is only that `the compiler' is too limited:

>As an example suppose I were to write this routine:
>dev_wait (csr)
>volatile int *csr;
>{
>	/* wait for the device to complete some operation */
>	while (*csr & DEVBUSY)
>		/* So this is in the kernel, reasonable example */
>		sleep (csr, PRI);
>}
>
>How could the compiler possibly know that the pointer passed
>at runtime might point to a volatile location (without the keyword)??

Ask the question this way:  Who calls dev_wait?  If you look at a
PDP-11 kernel, it may look like this:

	dev_open(dev)
		dev_t dev;
	{
		register struct devdevice *devaddr = DEVADDR;
		...
		dev_wait(&devaddr->dev_csr);
		...
	}

So the caller (here dev_open()) *does* know the address being accessed
(after a bit of flow analysis).  All the compiler need do (`all' he
says :-) ) is pass that information on down into the generation of
dev_wait().

`But wait!' you object.  `What if dev_open is in a separate file?'

Compilation (including alias and volatility analysis) need not occur
until `link' time.

`But wait!' you object.  `What if I read the address in at run-time?'

	main()
	{
		int *ip;
		...
		... read(fd, (char *)&ip, sizeof(ip));
		...
		while (*ip & BUSY)
			/* void */;
		...
	}

Is *ip volatile?  I cannot say---but neither can you.  The compiler
(which may be disguised as a linker) does not know either.  It must
therefore assume that it is volatile.

The key point here is that there is no algorithmic way to determine
volatility in this worst case---so any competent programmer must
assume that, if there are any volatile addresses, this code may refer
to one.  The programmer's only other option is to decree that the
program must never read an address that *is* volatile.  A programmer
who makes such a decree is certain to be surprised by a user.  If
you meant that *ip had better not be volatile, you should check ip:

	if (is_volatile(ip)) {
		fprintf(stderr, "%s: bad input data in %s\n",
			progname, infile);
		exit(EX_DATAERR);
	}
	while (*ip & BUSY)
		/* void */;

How will you write is_volatile()?  On an IBM PC you might say

	if ((unsigned long)ip >= 640*1024L) ...

Once you have done that, the compiler can (by a bit of range checking)
also determine that *ip is not volatile.

`But wait!' you say.  `Even a very fancy optimising ``compiler''
(linker) is going to miss *some* things.  Why, we can use some fancy
mathematics to prove that it cannot catch everything.'

That is so.  But how often will this occur in practise?  Today,
probably all the time; but tomorrow?  Five years from now?  Fifty?
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris at mimsy.umd.edu	Path:	uunet!mimsy!chris



More information about the Comp.lang.c mailing list