chris@mimsy.UUCP (Chris Torek) (12/04/88)
>In article <21560@apple.Apple.COM> desnoyer@Apple.COM (Peter Desnoyers) writes: >>pet peeve - It is a common thing to have to write a zero to a device >>register. The obvious code, (* reg_addr) = 0, often results in: >> xor reg_addr, reg_addr I would say not `often' but `sometimes'. In article <13784@oberon.USC.EDU>, blarson@skat.usc.edu (Bob Larson) writes: >... Most 68000 compilers would use the clr instruction, which does have >the undesired side effect of doing an (ignored) read though. (True only on the 000; the 010 and 020, and presumably 030, clr does not read before write.) >>Unfortunately I don't think specifying bus semantics is within the >>purview of the ANSI committee ... This part is true. >>and volatile is not sufficient to force the desired activity. >Fortunatly you are wrong, and volitile is sufficient. Volatile (note the spelling: compilers will not accept the `volitile' non-keyword) does imply---I will not use the word `guarantee' without checking the exact wording---that using an XOR or read-before-write-CLR instruction to clear a volatile location is incorrect. Consider, however, a machine which is only word-addressible, on which byte references compile to shift-and-mask sequences. I do not know what the compiler must or even should do if given the following code: struct foodev { char c1, c2; }; f() { register volatile struct foodev *p; ... /* set up p */ p->c1 = 0; } The only way to set p->c1=0 is for the compiler to use a sequence like load 0(rP),r1 and #ff00,r1,r1 store r1,0(rP) I would suggest that the compiler complain about volatile references that it cannot compile `properly'. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/04/88)
In article <14832@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: >I would suggest that the compiler complain about volatile references >that it cannot compile `properly'. Sounds like a reasonable suggestion to me. After all, if the programmer specified "volatile" it is safe to assume that he had a reason for doing so, and if it can't be honored then something is probably going to break.
desnoyer@Apple.COM (Peter Desnoyers) (12/06/88)
In article <9059@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >In article <14832@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: >>I would suggest that the compiler complain about volatile references >>that it cannot compile `properly'. > >Sounds like a reasonable suggestion to me. >After all, if the programmer specified "volatile" it is safe to >assume that he had a reason for doing so, and if it can't be honored >then something is probably going to break. The uncompilable example given was 'volatile char foo' on a word-oriented machine. If 'foo' is a hardware register, methinks a compiler error message is insufficient. You really should fire the person who designed such a f***-up. It ranks up there with write-only memory. 1/2 :-) Peter Desnoyers
tim@crackle.amd.com (Tim Olson) (12/06/88)
In article <21686@apple.Apple.COM> desnoyer@Apple.COM (Peter Desnoyers) writes: | In article <9059@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: | >In article <14832@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: | >>I would suggest that the compiler complain about volatile references | >>that it cannot compile `properly'. | > | >Sounds like a reasonable suggestion to me. | >After all, if the programmer specified "volatile" it is safe to | >assume that he had a reason for doing so, and if it can't be honored | >then something is probably going to break. I was speaking to Richard Relph about this subject, and he brought up the problem of unaligned accesses through a pointer to a volatile object which is larger than a char, but is not properly aligned [what a mouthful!]. These also require multiple accesses to be performed "correctly." What should be done here? -- Tim Olson Advanced Micro Devices (tim@crackle.amd.com)
gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/07/88)
In article <23706@amdcad.AMD.COM> tim@crackle.amd.com (Tim Olson) writes: >I was speaking to Richard Relph about this subject, and he brought up >the problem of unaligned accesses through a pointer to a volatile object >which is larger than a char, but is not properly aligned [what a >mouthful!]. These also require multiple accesses to be performed >"correctly." What should be done here? You're already in the realm of entirely implementation-dependent behavior. There is no way to obtain via pure C constructs such a pointer along with a guarantee that it can be used to access something. I would recommend that the implementation warn about the attempted misaligned access in such a case, IF it can readily determine that this is being attempted. Whether it should generate code to access the object piece by piece is debatable; it's not required by the Standard and would impose a large burden to support in most implementations. "volatile" really is not an issue here. Sequential access of multiple portions of an object does not violate the requirements of the Standard (section 2.1.2.3). For objects specified as "volatile", failure to access or multiple accesses -- when not specified as such for the abstract machine in the source code -- would be a violation. P.S. The above is my own interpretation, not necessarily X3J11's.
henry@utzoo.uucp (Henry Spencer) (12/07/88)
In article <23706@amdcad.AMD.COM> tim@crackle.amd.com (Tim Olson) writes: >...the problem of unaligned accesses through a pointer to a volatile object >which is larger than a char, but is not properly aligned... > What should be done here? "Bus error -- core dumped." :-) More seriously, it's really not entirely clear just how strong a guarantee of atomicity you get from X3J11's words about volatile. I doubt that the rules are intended to forbid pdp11 floating point, which necessarily uses multiple accesses per object because no pdp11 has a 64-bit memory bus. I think you have to consider volatile as meaning "no surprises" -- is it really a surprise that a large unaligned object requires more than one access? -- SunOSish, adj: requiring | Henry Spencer at U of Toronto Zoology 32-bit bug numbers. | uunet!attcan!utzoo!henry henry@zoo.toronto.edu
rns@se-sd.sandiego.ncr.com (Rick Schubert) (12/08/88)
I probably shouldn't do this, since getting involved in such discussions usually causes more grief than satisfaction, but I just attended a motivational talk encouraging risk-taking, so here goes. In article <14832@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: ::In article <21560@apple.Apple.COM> desnoyer@Apple.COM (Peter Desnoyers) writes: :::pet peeve - It is a common thing to have to write a zero to a device :::register. The obvious code, (* reg_addr) = 0, often results in: ::: xor reg_addr, reg_addr :::and volatile is not sufficient to force the desired activity. ::Fortunatly you are wrong, and volitile is sufficient. :Volatile (note the spelling: compilers will not accept the `volitile' :non-keyword) does imply---I will not use the word `guarantee' without :checking the exact wording---that using an XOR or read-before-write-CLR :instruction to clear a volatile location is incorrect. I won't make any guarantees either, but I believe that using an XOR is NOT incorrect as far as the dpANS is concerned (although it would be a poor quality of implementation). Quoting from the May 13, 1988 Draft (page 62, lines 10-11): What constitutes an access to an object that has volatile-qualified type is implementation-defined. I don't think we (X3J11) changed this at the September, 1988 meeting. My recollection from past discussions on this is that we didn't think it would be feasible to specify precisely how many times and in what ways a volatile object should be accessed. It's a very tricky area because volatile deals with inherently machine-dependent constructs (e.g. device registers), whereas the Standard is trying to specify portable (or machine-independent) behavior. Since `access' depends on such things as the instruction set, object size, and alignment, it is pretty much outside the domain of X3J11 to make such a specification. Now, in a practical sense, if a machine has a device register that, in some situation needs to have the value 0 stored in it, and if reading its value (1 or more times) before writing a 0 would cause undesirable behavior, then there must be some instruction (or instruction sequence) to store a 0 without a read (or multiple writes). If the compiler writer does not generate such an instruction, but instead uses (for example) XOR because XOR is faster, then the compiler writer made a poor (to put it mildly) choice, but I don't think you could take that person before an official X3J11 court and get a conviction. XOR still can be used for non-volatile objects, so your benchmarks won't have to suffer. :Consider, :however, a machine which is only word-addressible, on which byte :references compile to shift-and-mask sequences. I do not know what :the compiler must or even should do if given the following code: : struct foodev { char c1, c2; }; : f() { : register volatile struct foodev *p; : ... /* set up p */ : p->c1 = 0; : } :I would suggest that the compiler complain about volatile references :that it cannot compile `properly'. :-- :In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) :Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris In article <23706@amdcad.AMD.COM> tim@crackle.amd.com (Tim Olson) writes: :I was speaking to Richard Relph about this subject, and he brought up :the problem of unaligned accesses through a pointer to a volatile object :which is larger than a char, but is not properly aligned [what a :mouthful!]. These also require multiple accesses to be performed :"correctly." What should be done here? : -- Tim Olson : Advanced Micro Devices I think these 2 examples demonstrate why X3J11 didn't try to specify the "correct" or "proper" behavior in such circumstances. I also don't think that either situation would come up in practice. Remember, `volatile' is primarily for accessing the hardware in a hardware-specific way; the hardware designers wouldn't [be so stupid as to] design an object that must be accessed in a specific way (e.g. a byte that must be accessed without touching the adjacent byte) without an instruction (or instruction sequence) to access the object in that way. Disclaimer 1: None of the above is an official X3J11 position. Disclaimer 2: Notice the "I believe"s and "I think"s, and be gentle if I am wrong. Disclaimer 3: Sorry if I got some of the secondary attributions wrong; I had trouble following some of chains of "In article ... ... writes:" Disclaimer 4: Spelling errors inside of quoted articles are not my fault; spelling errors outside of quoted articles are "spell"s fault. -- Rick Schubert (rns@se-sd.sandiego.NCR.COM)
raeburn@athena.mit.edu (Ken Raeburn) (12/08/88)
In article <1988Dec6.180614.23949@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes: >I think you have to consider volatile as meaning "no surprises" -- is >it really a surprise that a large unaligned object requires more than one >access? This sounds a lot more reasonable.... Chris Torek's article got me thinking. On a machine that can't do single-byte accesses, device-driver routines shouldn't have volatile char structure components. It wouldn't make sense. (Getting slightly off the subject here....) But what about variables (automatic, global, or static) that are used in the neighborhood of setjmp/longjmp calls? If I have a variable that is a char or small enum (which my compiler might want to fit into a char under normal circumstances), what happens when I declare them volatile? I think that, given sufficiently bizzarre machine descriptions, possibly any type (except maybe int?) might require multiple accesses (multiple reads, or reads-and-writes) for at least some machine types. The "no-surprise" guideline seems like the only way to make sense of this across different machine types. (My impression is that the use of "volatile" for setjmp/longjmp is covered under "portability" rather than "machine-specific device drivers", and I should be able to do something reasonable here in a portable way. Or should I?) (Hope this hasn't gone by in discussions already... I only read news off-and-on....) Can the compiler allocate extra storage around a "volatile" variable (that is not part of a structure and does not have external linkage) and randomly smash it when this variable needs to be accessed? Or is it valid to just have it complain that this particular machine type can't do that particular operation? Actually, my own interest in the uses of "volatile" is more in the line of device drivers... Real Soon Now I should get around to trying to build some of the BSD drivers with gcc, really I will... I was just wondering about this point. _kr
gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/09/88)
In article <8356@bloom-beacon.MIT.EDU> raeburn@athena.mit.edu (Ken Raeburn) writes: >But what about variables (automatic, global, or static) that are used >in the neighborhood of setjmp/longjmp calls? If I have a variable >that is a char or small enum (which my compiler might want to fit into >a char under normal circumstances), what happens when I declare them >volatile? I think that, given sufficiently bizzarre machine >descriptions, possibly any type (except maybe int?) might require >multiple accesses (multiple reads, or reads-and-writes) for at least >some machine types. The "no-surprise" guideline seems like the only >way to make sense of this across different machine types. (My >impression is that the use of "volatile" for setjmp/longjmp is covered >under "portability" rather than "machine-specific device drivers", and >I should be able to do something reasonable here in a portable way. >Or should I?) I don't understand what the problem is. Upon a longjmp()ed return from a matching setjmp(), all accessible objects have values as of the time longjmp() was called, except that the values of objects of automatic storage duration that are local to the function containing the invocation of the corresponding setjmp() macro that do not have volatile-qualified type and have been changed between the setjmp() invocation and longjmp() call are indeterminate. [From the proposed standard.] The only mention of "volatile" is that a volatile auto is guaranteed to have the correct value, even though a non-volatile auto in the same function may have been cached and therefore have an incorrect stored value. (Otherwise, optimizers would have to give special treatment to use of setjmp/longjmp.) "volatile" really has nothing to do with setjmp/longjmp semantics; the explicit note that its use could make a local auto safe even across longjmp() was just weakening the exception being made for local autos due to the effects of optimization, since it was clear that "volatile" semantics permitted this extra guarantee. >Can the compiler allocate extra storage around a "volatile" variable >(that is not part of a structure and does not have external linkage) >and randomly smash it when this variable needs to be accessed? Or is >it valid to just have it complain that this particular machine type >can't do that particular operation? The compiler can allocate extra storage in many cases, but it's not necessary here. Use of "volatile" does not give the compiler license to fail to translate a conforming program. Warnings can be issued any time the implementor wishes.
raeburn@athena.mit.edu (Ken Raeburn) (12/17/88)
>I don't understand what the problem is.
My problem was with the idea being discussed that references to a
volatile variable translate to exactly one memory reference. On a
machine that may require more than one memory access to retrieve or
store one of the C data types (especially if you deal with entire
structures at a time) this wouldn't work.
Being more awake this time, I would point out that any piece of
machine-independent, portable code could have "volatile" declarations
added without ill effect (except perhaps some loss of optimization);
my references to setjmp/longjmp were just reaching for some case
outside of device drivers and the like where use of "volatile" would
be useful, but that's beside my point. Since any type could have the
"volatile" qualifier, the one-access stuff is out the window.
I was basically trying to find out something that somebody posted a
short while later, which I hadn't noticed before in the draft
standard: "What constitutes an access to an object that has
volatile-qualified type is implementation-defined."