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