(I've put this back on the mailing list - I assume you meant to do that, 
and just pressed the wrong "reply" button.)

On 23/08/2012 01:06, William Swanson wrote:
> On Wed, Aug 22, 2012 at 2:28 PM, David Brown <david.br...@hesbynett.no> wrote:
>> On 22/08/12 22:15, William Swanson wrote:
>>> Besides being smaller and faster, this actually does the right thing.
>>
>> No, it does not "do the right thing".  It might do what you want - but it
>> does not implement the C code you wrote.  Single "state" is volatile, the
>> code generated by the compiler is optimal.
>
> According to the ANSI standard, all writes to a "volatile" variable
> must occur before the next sequence point, and reads should assume
> that the value can change at any time (but a "read" is implementation
> defined). Since the "|=" operator doesn't introduce a sequence point,
> the code I suggested would be perfectly correct according to the
> standard. The implied read from the "|=" operator could be placed next
> to the final write, and the peephole optimizer could then merge the
> two with no change in semantics.
>
> The compiler's current output is also correct, but it's certainly not optimal.
>

I can see your point, but I am not convinced it is correct.  You are 
talking about a very grey area of the C specs here - "volatile" is 
simply not well enough specified in the C standards.  There was a 
well-publicised paper recently which looked at code generated by a 
variety of compilers for different volatile constructs, which concluded 
that most (or all, I think) compilers got things wrong in some 
circumstances.  The obvious conclusion to take from that is that you 
must keep volatile code simple.  If not, then either /you/ will get it 
wrong, or the /compiler/ will get it wrong.  And even if both are right, 
the hardware can still be a limitation.  This very example shows the 
problems caused by complex volatile code - you agree the compiler's 
output is correct based on the source code, yet it does not do what you 
want it to do or think it should do.

So by the coding rules I use, the code you wrote is wrong - regardless 
of what the compiler generates, or even whether or not it works.

>> First off, you can check that the C code you wrote is what you meant to
>> write - the shift operation here looks very out of place.
>>
>> [...] Your "desired" code is not atomic, and will cause trouble.
>
> That code is designed to work correctly even if "state" changes
> mid-expression. Only the final "|=" operation needs to be atomic. Yes,
> I realize that this code is being tricky.

Then separate the two operations into two lines of code:

uint8_t newBits = (state >> 1) & DIRTY_FLAG;
state |= newBits;

That makes the code much clearer - and it explicitly shows that the two 
operations can be split up.  Otherwise you've got a maintenance problem 
for the future when a new programmer tries to figure out what works or 
does not work.

And maybe you'll be lucky and the "|=" will be implemented atomically 
with that code.  Simple statements are critical to getting volatile 
right, and it gives the compiler the best chance.  There are no 
guarantees, however.

>
>> The obvious first step towards correct code is to put the "DIRTY_FLAG" in
>> its own byte - or at least in a byte containing simple flags and not
>> requiring shifts.
>
> Since relying on an atomic "|=" isn't an option, and GCC's atomic
> "__sync_fetch_and_or" intrinsic doesn't exist on this platform, it
> looks like I will have to re-design the algorithms along the lines you
> are suggesting. If that's not possible (and it probably isn't without
> a CAS or other atomic primitive), I can always fall back on
> __eint()/__dint() for the critical sections.
>

Another option is a single inline assembly call for the "|=" if the 
above code split does not help.



------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Mspgcc-users mailing list
Mspgcc-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mspgcc-users

Reply via email to