----- Original Message ----- From: "Roberto Padovani" <padovan...@gmail.com> To: "GCC for MSP430 - http://mspgcc.sf.net" <mspgcc-users@lists.sourceforge.net> Sent: Monday, July 03, 2006 5:31 PM Subject: Re: [Mspgcc-users] Code generation question
> I'll be brief because it's beer time here. > It's important to set things in perspective ! > yes, I'm convinced that you get the same code with opts and that there's a bug; > but, I can't agree to the atomicity of the writes, or at least I > didn't explain myself. > > Here's what is dangerous with irq enabled: > > two = P6IN + P6IN; // or any other way in which you write directly to "two" > > beacuse you inevitably get 2 instructions that sequentially write at > the memory address of "two": if an interrupt happens between, it's a > mess..... I can't see what you mean with atomicity. > You most certainly do *not* get two instructions that write to the memory address of "two". You get two reads of P6IN (since it is volatile), you get instructions to do the adding (which may be combined with the reads), and you get a single write to "two". C does not make any absolute guarentees that "two" will not be accessed twice - but only on a brain-dead architecture like the PIC would it make sense, so you can be sure your compiler will not split this into two writes. > >The compiler does not know or care about > >interrupt functions - it assumes that it has full control of "two" while > > generating code, and can do what it likes with it. > > it's true: YOU have to take care of writing C code correctly so that > the compiler won't do too much of what it likes > > This is safer: > > tmp = P6IN + P6IN; // or any other way that I would better like > two = tmp; > > because this is what atomic write to a global variable means. > No, it is not safer. You still have no guarentees about the number of writes to "two" - the compiler is free to implement "tmp" as an alias to the global variable "two" if it wants. Again, you can be sure it will not do this simply because you can be confident that the compiler will generate sensible code - but your level of security is exactly the same. In each case, you can increase the level of confidence by making "two" volatile - but in each case, your confidence level is already very high (though not guarenteed). Understanding your compiler and your target is vital. Adding extra unnecessary code "just in case" is often a bigger risk through human error (yours, or the next guy who modifies the code). > And about the usage of the compiler, I've seen that they are typically > more effective in removing unnecessary variables (i.e. re-using > registers), rather then deciding what is the best allocation....this > helps to ensure that the instructions work on register operands as > often as possible. Declaring and using locals has no drawback. > Using locals is obviously a good thing - it is adding unneccessary extra variables that I disagree with. Your reasons should be based on what makes your code easier to read, write and understand - the examples you have given don't fulfill these criteria. Just as using a comment such as "int tmp; // This is for temporary storage" adds verbosity and therefore hides the real meaning of the code, so your additional "tmp" variables give nothing and dilute the code. So unnecessary variables have a very real drawback in the quality of the source code. As a more minor point, they can have an adverse effect on the quality of the target code, at least if debugging prevents the compiler from using its most agressive optimisations. mvh., David > Cheers, > > R. > > > 2006/7/3, David Brown <da...@westcontrol.com>: > > > > ----- Original Message ----- > > From: "Roberto Padovani" <padovan...@gmail.com> > > To: "GCC for MSP430 - http://mspgcc.sf.net" > > <mspgcc-users@lists.sourceforge.net> > > Sent: Monday, July 03, 2006 3:35 PM > > Subject: Re: [Mspgcc-users] Code generation question > > > > > > > >> if you really want that single instruction as a function by itself and > > > >> you want it to write directly in the global variable, then you should > > > >> at least declare it naked. > > > >> > > > > > > > >Perhaps this is a case where we have misunderstood each other - as far as > > I > > > >can tell, you said that Grant's code should be split with an extra > > function, > > > >and I disagreed. Did I misunderstand you? > > > > > > if this was the source: > > > ------------VERSION 1 ------------------ > > > #include .... > > > unsigned int two; > > > > > > void foo(){ > > > two = P6IN + P6IN; > > > } > > > > > > void main(){ > > > .... > > > foo(); > > > .... > > > ..make something with "two"... > > > } > > > --------------------------- > > > > > > I would have rather rewritten it as: > > > > > > > > > -----------------VERSION 2-------- > > > #include .... > > > unsigned int two; > > > > > > unsigned int foo(){ > > > unsigned int tmp; > > > > > > tmp = P6IN; > > > tmp += P6IN; > > > return tmp; > > > } > > > > > > void main(){ > > > .... > > > two = foo(); > > > .... > > > ..make something with "two"... > > > } > > > ----------------------------- > > > > > > and I would especially avoid writing IOCCC style code like: > > > > > > unsigned int foo(){ > > > unsigned int tmp = P6IN; > > > return tmp + P6IN; > > > } > > > > > > > It can make sense to avoid having foo() access a global variable - avoiding > > globals is frequently considered good practice. But it is only useful if > > "two" is local to main() - if you do decide to use "two" as a global, it is > > preferable for it to be written inside foo() rather than in main(), assuming > > that's it's only use in the program. It's a matter of encapsulating the > > change - consider "foo" to be a function that sets "two", rather than a > > function that returns a double sample from P6IN. > > > > I fail to see that your "IOCCC" style is significantly worse than your > > original style, although personally I put parenthesis around calculated > > return values to make them a little clearer. You have still failed to > > convince me that using "tmp" has any merit - I think (assuming you don't > > want to set "two" in "foo") the shorter and neater version is better: > > > > unsigned int foo(void) { > > return (P6IN + P6IN); > > } > > > > But ultimately, we are arguing style here - and that is definitely a matter > > of taste. I hope I have shown you by now that there is no difference in the > > generated code for such short functions, regardless of whether "tmp" is used > > or not. > > > > > which is exactly the same, but it's the highway to coffe and GDB. > > > > > > > > > >> I came across a similar problem writing for another processor > > architecture > > > >> (er OK I admit it a PIC). The line > > > >> > > > >> P2 = a+b+c; > > > >> > > > > > > > >In this case, either P2 was declared incorrectly (i.e., it was not > > declared > > > >as a volatile), or the compiler generated incorrect code. > > > > > > > >In general, yes, the compiler is free to use "two" to store half the > > > >calculation. In practice, of course, it will not - as you say, it will > > use > > > >a register (on the PIC, it makes sense to use the global as a temporary > > > >storage, since it has no real registers). But the only way to make > > > >absolutely sure that "two" is not written in two steps is to make "two" a > > > >volatile as well. > > > > > > Apart from the fact that my limited knowledge of volatiles prevents me > > > to understand how it is possible to ensure that two is not written in > > > two steps, John highlighted the most important reason for which you > > > should write that foo function the way I think. > > > > > > > The way in which global data is written is only partially governed by the > > use of "volatile". In particular, you need an understanding of atomic > > accesses - "volatile" is no guarentee of atomicity. What you can be sure of > > is that on a msp430, any simple type of 16-bit or 8-bit size will be writen > > atomically. This is not guarenteed by C (and is not necessarily true on > > other architectures - a 16-bit DSP may not be able to write 8-bit data > > atomically). You can also be confident that the compiler will never write > > to a global variable more often than you tell it to - the compiler never > > intentionally generates such sub-optimal code (again, this is not > > necessarily the case on C-unfriendly architectures). If the variable is > > volatile, it will be written *exactly* as often as you specify (once the bug > > is fixed!). But larger variables, such as a 32-bit variable, cannot be > > written atomically without disabling interrupts. > > > > > > > If you get an interrupt in the middle of the two readings of version > > > 1, you'll find yourself with an inconsistent value of "two".....and > > > Murphy assures you that the service routine will be using "two" for > > > some critical stuff. > > > In this case, you should declare version 1 of foo() as "critical", > > > with all the pros and cons of that kind of functions. > > > > > > > It is important to know when and how your global data is read and written, > > as it forms part of the interface between the functions. Using "critical" > > is one way to ensure the safety of the code - but it is not the only way. > > Examining the generated code and understanding the underlying architecture > > is also a valid way to tell when you can assume "two" is written atomically > > (it's safe with msp430-gcc, but not with avr-gcc, for example). > > > > > With version 2 of foo(), there's never an inconsitency...in the worst > > > case you'll have an old value of "two" (not updated yet), but this is > > > a far more predictable behaviour to handle. > > > > > > > That's not actually correct - and possibly even a dangerous assumption if > > you believe it applies to other sorts of data (such as 32-bit data). You > > have no more or less guarentees with version 2 code. Consider that the > > compiler can happily inline the foo() code into main() and eliminate the > > extra temporary variable - these are perfectly valid optimisations. The > > resulting internal version of the code is the same in both versions. In > > each case, the compiler need only ensure that "two" contains the correct, > > consistent value before calling any code it cannot see while generating the > > code for main() and/or foo(). The compiler does not know or care about > > interrupt functions - it assumes that it has full control of "two" while > > generating code, and can do what it likes with it. If you want to be more > > precise, your only recourse is to make "two" volatile, and again it does not > > matter which version you use. > > > > Having said that, in practice the compiler will write to "two" atomically in > > each case, regardless of whether it is set in main() or foo(), and > > regardless of whether you add an extra local variable or not. As I said, it > > is important to know how your compiler and your target work, in particular > > when using interrupts. > > > > mvh., > > > > David > > > > > > > R. > > > > > > Using Tomcat but need to do more? Need to support web services, security? > > > Get stuff done quickly with pre-integrated technology to make your job > > easier > > > Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo > > > http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 > > > _______________________________________________ > > > Mspgcc-users mailing list > > > Mspgcc-users@lists.sourceforge.net > > > https://lists.sourceforge.net/lists/listinfo/mspgcc-users > > > > > > > > > > > > > > > > > Using Tomcat but need to do more? Need to support web services, security? > > Get stuff done quickly with pre-integrated technology to make your job easier > > Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo > > http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 > > _______________________________________________ > > Mspgcc-users mailing list > > Mspgcc-users@lists.sourceforge.net > > https://lists.sourceforge.net/lists/listinfo/mspgcc-users > > > > Using Tomcat but need to do more? Need to support web services, security? > Get stuff done quickly with pre-integrated technology to make your job easier > Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo > http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 > _______________________________________________ > Mspgcc-users mailing list > Mspgcc-users@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/mspgcc-users > > >