Bug 15456 - writing to volatile pointer in C++ may produce extra read after write
Summary: writing to volatile pointer in C++ may produce extra read after write
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 2.96 (redhat)
: P2 minor
Target Milestone: 3.1.x/3.2.x
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-05-15 08:35 UTC by Michael Bukin
Modified: 2005-07-23 22:49 UTC (History)
1 user (show)

See Also:
Host: i386-redhat-linux
Target:
Build:
Known to work: 3.2.3 3.2.2 3.3.3
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Bukin 2004-05-15 08:35:05 UTC
Accessing hardware registers mapped in address space requires
the use of volatile pointer - to leave all accesses in the result
and not optimize them away.  But writing to volatile pointer in C++
may result in extra read instruction right after write,
which may obviously trigger some undesired action in hardware,
as memory access actually accesses mmapped hardware register.

The program below demonstrates this behaviour, when compiled with
bash$ gcc -O2 -S test_volatile_ptr.cpp

Here is a short snippet of assembly output, which you should look for:
	movl	$128, (%eax)
        ...
	movl	(%eax), %eax   ; I don't like this one

bash$ gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/2.96/specs
gcc version 2.96 20000731 (Red Hat Linux 7.3 2.96-110)

Complete source code:

cat >test_volatile_ptr.cpp <<EOF
// <test_volatile_ptr.cpp>

// Pointer to hardware registers mapped in our address space.
// volatile is to prevent read/write optimizations.
volatile unsigned long *addr;

// Helper function to set memory mapped register.
inline void _set (unsigned long _offs, unsigned long _data)
{
  addr[_offs] = _data;
}

// This one produces correct assembler output.
void init_good ()
{
  addr[0] = 0x80;
}

// This one adds extra read after write,
// Which in case of memory mapped hardware access
// may trigger undesired action in hardware.
void init_bad ()
{
  _set (0, 0x80);
}

// </test_volatile_ptr.cpp>
EOF
Comment 1 Andrew Pinski 2004-05-15 12:10:02 UTC
Fixed in at least 3.2.2, time to update your gcc.