This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Bad libstdc++-v3/config/cpu/i486/bits/atomicity.h [An ia32 LOCK/XADD bug.]


It looks like sysdeps/i386/i486/atomicity.h in glibc is copied from
libstdc++-v3. Here is the bug report on __exchange_and_add.


H.J.
====
On Wed, May 16, 2001 at 12:55:36PM -0700, H . J . Lu wrote:
> Has anyone run LD_PROFILE lately? I got
> 
> # LD_PROFILE=libc.so.6 ls
> zsh: 4096 illegal hardware instruction  LD_PROFILE=libc.so.6 ls
> 
> I will track it down.
> 
> 

It turned out it might be a bug in glibc:

# gcc a.c
# gdb a.out
(gdb) r
3
4, 3
4

Program received signal SIGILL, Illegal instruction.
exchange_and_add_2 (mem=0x80496e8, val=2) at a.c:23
23        __asm__ __volatile__ ("lock; xaddl %0,%2"
(gdb) disass exchange_and_add_2
Dump of assembler code for function exchange_and_add_2:
0x8048554 <exchange_and_add_2>: push   %ebp
0x8048555 <exchange_and_add_2+1>:       mov    %esp,%ebp
0x8048557 <exchange_and_add_2+3>:       mov    0x8(%ebp),%eax
0x804855a <exchange_and_add_2+6>:       mov    0xc(%ebp),%edx
0x804855d <exchange_and_add_2+9>:       lock xadd %edx,%edx
0x8048561 <exchange_and_add_2+13>:      mov    %edx,%eax
0x8048563 <exchange_and_add_2+15>:      pop    %ebp
0x8048564 <exchange_and_add_2+16>:      ret    
End of assembler dump.

It looks like

	lock xadd %edx,%edx

is an illegal instruction on ia32.  I cannot find anything in Intel
reference manual to say you cannot have LOCK on insn where DST/SRC are
reg or same. My questions are

1. How to write a correct exchange_and_add? Is exchange_and_add_1 ok?
2. If "lock xadd %edx,%edx" is really an illegal instruction on ia32,
how should we fix gas to detect that?


H.J.
---
#include <stdio.h>
#include <inttypes.h>


static volatile uint32_t fromidx;

static inline uint32_t
__attribute__ ((unused))
exchange_and_add_1 (volatile uint32_t *mem, uint32_t val)
{
  register uint32_t result;
  __asm__ __volatile__ ("lock; xaddl %0,%1"
			: "=r" (result), "=m" (*mem)
			: "0" (val), "1" (*mem));
  return result;
}

static inline uint32_t
__attribute__ ((unused))
exchange_and_add_2 (volatile uint32_t *mem, uint32_t val)
{
  register uint32_t result;
  __asm__ __volatile__ ("lock; xaddl %0,%2"
			: "=r" (result), "=m" (*mem)
			: "0" (val), "1" (*mem));
  return result;
}

int
main ()
{
  uint32_t newfromidx;
  fromidx = 3;
  printf ("%d\n", fromidx);
  newfromidx = exchange_and_add_1 (&fromidx, 1);
  printf ("%d, %d\n", fromidx, newfromidx);
  fromidx = 4;
  printf ("%d\n", fromidx);
  newfromidx = exchange_and_add_2 (&fromidx, 2);
  printf ("%d, %d\n", fromidx, newfromidx);
  return 0;
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]