[comp.std.c] observability

flaps@dgp.toronto.edu (Alan J Rosenthal) (09/07/89)

bvs@light.uucp (Bakul Shah) writes:
>I have some questions about `observable behavior'.  How does this
>concept interact with `volatile' variables? with debuggers? with
>shared memory?

Debuggers and shared memory are not specified in the ansi C standard.
That is, there does not exist behaviour of debuggers or of shared memory
that violate the standard.

Many people claim that "volatile" is meaningless since it is not observable.

>Is a program with *no* output of any kind observable?

Yes, you can observe that it produced no output, a different observation from
observing it producing some output.  However, the ansi C standard probably
doesn't prevent "int main() { return(0); }" from outputting, as a concession to
verbose environments.  So there might not exist standard-violating behaviour
for the execution of a program which produces no output.

ajr

barmar@think.COM (Barry Margolin) (09/07/89)

In article <1989Sep6.183349.2866@jarvis.csri.toronto.edu> flaps@dgp.toronto.edu (Alan J Rosenthal) writes:
>Many people claim that "volatile" is meaningless since it is not observable.

Here's a simple example where I think "volatile" is meaningful:

int global_variable;

handler() {
	global_variable = 2
}

main() {
	signal(SIGSOMETHING, handler);
	global_variable = 1;
	<expression that raises SIGSOMETHING>;
	printf("%d", global_variable);
}

I believe that it would be valid for an implementation to print either
1 or 2, because the lack of a "volatile" modifier permits
global_variable's value to be cached between the assignment and the
printf.  Adding a "volatile" modifier disallows this optimization, so
the program must print 2.

>bvs@light.uucp (Bakul Shah) writes:
>>Is a program with *no* output of any kind observable?

This reminds me of the old stories about an optimizing Fortran
compiler that was doing amazingly well on benchmarks because it
optimized away the entire program because it had no I/O statements.

Barry Margolin
Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/07/89)

In article <1989Sep6.183349.2866@jarvis.csri.toronto.edu> flaps@dgp.toronto.edu (Alan J Rosenthal) writes:
>Many people claim that "volatile" is meaningless since it is not observable.

In many situations it IS observable.

richard@aiai.ed.ac.uk (Richard Tobin) (09/08/89)

In article <28946@news.Think.COM> barmar@think.COM (Barry Margolin) writes:
>Here's a simple example where I think "volatile" is meaningful:
 [Handler example deleted]

Another case is local variables in routines that call setjmp().
Non-volatile auto variables whose value has been changed since the
call to setjmp() may have arbitrary values after a longjmp().
Volatile variables will have their correct values.

-- Richard
-- 
Richard Tobin,                       JANET: R.Tobin@uk.ac.ed             
AI Applications Institute,           ARPA:  R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk
Edinburgh University.                UUCP:  ...!ukc!ed.ac.uk!R.Tobin

bvs@light.uucp (Bakul Shah) (09/08/89)

In article <10962@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>In article <1989Sep6.160709.4890@light.uucp> bvs@light.UUCP (Bakul Shah) writes:
>>I have some questions about `observable behavior'.  How does this
>>concept interact with `volatile' variables? with debuggers? with
>>shared memory?
>
>"Observable behavior" was my own terminology.  The proposed Standard
>doesn't go into this in great detail.

I am glad you used that term as `observability' very nicely captures
the semantics of volatile objects, modifying files etc.  Observability
is important but not necessarily obvious to many.  One reason I wanted
some discussion was because the pANS doesn't say much about it.

>I believe the constraints on volatile variables are sufficient to
>ensure that accesses really do occur according to the abstract
>machine.  There is a bit of deliberate vagueness about the atomicity
>of the access.

Well, using observability as an explicit guiding principle this
vagueness could have been tightened some more.  For instance, one can
say that each time a volatile object is referenced at source level for
reading/writing, _atleast_ one access of the appropriate kind is made.
If you are willing to admit existence of a minumum size object that
can be changed all at once, one more guarantee can be made (to the
memory mapped IO crowd): assigning to this object will not result in a
read access.  The last makes sense because the effect is observable
and yet, the compiler need not know why.

>Debugging environments are beyond the scope of the Standard.
>How useful yours is depends on the care put into it by the vendor.
> ...
>
>Generally, it would be too hard for a compiler to perform the analysis
>necessary to determine how much code generation could be omitted due
>to its having no observable effect.  Some local optimizations are
>expected, but without a very smart compiler the only safe thing would
>be for it to ensure that side effects have code executed to cause them.

There are compilers that throw out things even when -g is specified
and rearrange code in their zeal to be the fastest.  When it comes to
optimization most compilers either stick to safe optimizations or do
some questionable ones.  In both cases observability can be used to
separate what is doable from what is not.

I realize that debugging environments and such are beyond the scope of
the pANS which why such guidelines can be very useful (may be as part
of the Rationale).

-- Bakul Shah <..!{ames,sun,ucbvax,uunet}!amdcad!light!bvs>

exspes@gdr.bath.ac.uk (P E Smee) (09/08/89)

In article <28946@news.Think.COM> barmar@think.COM (Barry Margolin) writes:
>This reminds me of the old stories about an optimizing Fortran
>compiler that was doing amazingly well on benchmarks because it
>optimized away the entire program because it had no I/O statements.

Totally valid in FORTRAN.  Since the spec does not require preservation
of faults/exceptions (and indeed a program which produces them is
probably invalid) and any flags are not guaranteed to come back from a
subroutine.  Any FORTRAN program which does no I/O, does not change its
arguments or return a value, does not modify any variables in COMMON
(external storage), and does not call any other subroutine or function
which might do any of these, can be gutted.  The optimized null
procedure is identically equivalent to the original in FORTRAN terms.
Similarly, any block of code which does not contribute to such effects
can be removed from the program.  The C standard imposes different
requirements, and it appears that this FORTRAN approach would not be
valid in C -- though one might ask why you would want to write a chunk
of code that has ZERO effect.

(The counter-example people inevitably come up with is 'maybe the
program is meant to be a timing loop'.  The tired answer is 'if you
want a time delay, you should tell the operating system to put you to
sleep for some period of time, rather than wasting CPU cycles twiddling
your thumbs.  The other users of your multi-user system will thank you
for it.)
-- 
 Paul Smee               |    JANET: Smee@uk.ac.bristol
 Computer Centre         |   BITNET: Smee%uk.ac.bristol@ukacrl.bitnet
 University of Bristol   | Internet: Smee%uk.ac.bristol@nsfnet-relay.ac.uk
 (Phone: +44 272 303132) |     UUCP: ...!mcvax!ukc!gdr.bath.ac.uk!exspes

poser@csli.Stanford.EDU (Bill Poser) (09/10/89)

In article <1989Sep8.091010.12450@gdt.bath.ac.uk> exspes@gdr.bath.ac.uk (P E Smee) writes:
>one might ask why you would want to write a chunk
>of code that has ZERO effect.

I sometimes do this during program development. I declare the data
structures and write the code that operates on them, leaving the i/o
to worry about later. I may want to compile at this point to check
for errors in the code.

exspes@gdr.bath.ac.uk (P E Smee) (09/11/89)

In article <10321@csli.Stanford.EDU> poser@csli.stanford.edu (Bill Poser) writes:
>In article <1989Sep8.091010.12450@gdt.bath.ac.uk> exspes@gdr.bath.ac.uk (P E Smee) writes:
>>one might ask why you would want to write a chunk
>>of code that has ZERO effect.
>
>I sometimes do this during program development. I declare the data
>structures and write the code that operates on them, leaving the i/o
>to worry about later. I may want to compile at this point to check
>for errors in the code.

Well, maybe.  Still, in that case you shouldn't be using an optimizing
pass of the compiler yet, and I at least would claim that a non-optimizing
compiler *shouldn't* go rearranging the code in any significant manner.
(And, I would also assert that a compiler *shouldn't* go throwing away
blocks of code simply because they don't do anything, without warning you
it's doing so -- again on grounds that people don't usually intend their
code to do nothing.)

Alternatively, take that as (yet another) reason for using C rather than
FORTRAN.

-- 
 Paul Smee               |    JANET: Smee@uk.ac.bristol
 Computer Centre         |   BITNET: Smee%uk.ac.bristol@ukacrl.bitnet
 University of Bristol   | Internet: Smee%uk.ac.bristol@nsfnet-relay.ac.uk
 (Phone: +44 272 303132) |     UUCP: ...!mcvax!ukc!gdr.bath.ac.uk!exspes

diamond@csl.sony.co.jp (Norman Diamond) (09/13/89)

In article <1989Sep8.091010.12450@gdt.bath.ac.uk> exspes@gdr.bath.ac.uk (P E Smee) writes:

> -- though one might ask why you would want to write a chunk
>of code that has ZERO effect.
>(The counter-example people inevitably come up with is 'maybe the
>program is meant to be a timing loop'.  The tired answer is 'if you
>want a time delay, you should tell the operating system to put you to
>sleep for some period of time, rather than wasting CPU cycles twiddling
>your thumbs.  The other users of your multi-user system will thank you
>for it.)

If it takes longer to process an interrupt than to wait for a certain
hardware operation to finish, then the other users will thank you for
coding your no-ops.  If the kernel is trying to access a shared list
of task control blocks, and the list is locked (for a very short time)
by another processor's kernel, and the kernel decides not to crash the
system by trying to put itself to sleep, then the other users will
thank you for it.

Yes, people sometimes write timing loops in Fortran or C, for exactly
the same reason as people sometimes write kernels, device drivers,
libraries, and compilers in C.  Only sometimes they have to turn off
the optimizer.

The quoted meta-answer is more tired than the original answer.

--
-- 
Norman Diamond, Sony Corporation (diamond@ws.sony.junet)
  The above opinions are inherited by your machine's init process (pid 1),
  after being disowned and orphaned.  However, if you see this at Waterloo or
  Anterior, then their administrators must have approved of these opinions.