On 22/08/12 22:15, William Swanson wrote:
> Hello!
> I recently discovered a problem that affects my entire code base. I
> often do things like this:
>
>      volatile unsigned char state;
>      ...
>      state |= (state>>  1)&  DIRTY_FLAG;
>
> Since ISR's might be trying to set DIRTY_FLAG at the same time, it is
> very important that the final "|=" instruction happens atomically,
> like with a "BIS.B foo,&state" instruction. This was my original
> expectation, but the compiler apparently generates code like this
> instead:
>
>      MOV.B&state, R15
>      MOV.B&state, R14
>      RRUM   #0x0001, R15
>      AND.B  #0x0002, R15
>      BIS.B  R14, R15
>      MOV.B  R15,&state
>
> As you can see, there is a window of about three instructions where
> changes from an ISR would be lost. I could surround this code with
> __eint() / __dint() calls, but that seems overkill. I really want the
> compiler to generate code like this:
>
>      MOV.B&state, R15
>      RRUM   #0x0001, R15
>      AND.B  #0x0002, R15
>      BIS.B  R15,&state
>
> 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.

>
> So, what do I do? Short-term options include rewriting the critical
> bits in assembly and/or inserting the __eint() / __dint() calls, but I
> am really looking for a more elegant long-term solution. Fixing the
> code generator would be one option, but adding set of intrinsics like
> __atomic_add() would also be nice, since those would document the
> intention as well.
>

There are various things you can do.

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.

Then you can look at doing /correct/ treatment of mixing data between an 
ISR and a main loop.  That means you don't mix different sorts of 
information within a single byte, but keep all your accesses simple so 
that they are atomic (or you disable interrupts, or provide additional 
locking mechanisms).  Your "desired" code is not atomic, and will cause 
trouble.  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.

If you want to get code generated they way you describe, you need to 
remove the "volatile" qualifier.  But the code may still fail because 
the operation is not atomic.

------------------------------------------------------------------------------
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