AXIS: EMC2 Blog|
Blog
About AXIS Get EMC2 Documentation Translations ETCH CNC Developer Homepages: Chris Radek Jeff Epler Related sites: linuxcnc.org linuxcnc wiki |
On 32-bit systems, the widest HAL types are 32 bits ('int' and 'float').
Given that operations like ddt quickly begin to show problems due to the
limited precision of float, why doesn't HAL provide a 64-bit floating-point
type ('double')? Update, 2008-03-26: Clarify that 64-bit stores are
guaranteed atomic on pentium and later systems, and link to some fancy
inline asm tricks for this purpose.
HAL works on the principle that updates to all values must be atomic, and currently all assignments to HAL pins are of the simple form *pin is therefore restricted to types for which gcc always generates atomic store operations.*pin = newvalue; Unfortunately, when *pin is double or volatile double, gcc at least sometimes generates sequences like so that even if each individual movl instruction is atomic, the full store of newvalue can be interrupted after only 4 of the 8 bytes have been changed.movl newvalue, %eax movl newvalue+4, %edx movl pin, %ecx movl %eax, (%ecx) movl %edx, 4(%ecx) Here's a program that demonstrates this problem:
which shows the behavior when compiled with 'gcc -O -mtune=i386 -S vd.c
-o -'. Removal of the 'volatile' qualifier from hal_double makes no
difference to the result.
What can be done about it? Personally, I'm adopting a "just wait" policy. On 64-bit systems, it will simply be possible to widen the HAL types to 64 bits and rely on the compiler to generate 'movq' instructions. Other possibilities include:
atomic64.h uses inline assembly to perform guaranteed-atomic reads and stores of 64-bit values, and provides C++ wrapper classes that make these types behave just like built-in types in arithmetic and assignment. 'double', 'unsigned long long' and 'long long' are supported. |
| [æ] |