Python 2.3 in testing

Martin v. Löwis martin@v.loewis.de
Sun Apr 27 21:11:00 GMT 2003


Matthias Klose <doko@cs.tu-berlin.de> writes:

> Btw, koenntest Du Dir mal den Vorschlag von Loren ansehen bzw. auf
> einer Mehrprozessormachine (falls Du sowas hast) testen?
> http://gcc.gnu.org/ml/libstdc++/2003-04/msg00407.html

Hab' gerade (vor zwei Wochen) frisch eine bekommen :-)

[I started answering in German, but now I see that it might be more
productive to send this in English to Loren as well]

This code looks incorrect. When I try to compile

struct X{
	_Atomic_word a;
};

void foo(struct X* s)
{
	__atomic_add(&s->a, 10);
}

I get

_Z3fooP1X:
	pushl	%ebp
	movl	%esp, %ebp
	movl	8(%ebp), %edx
.L2:
	movl	_ZZ18__exchange_and_addPViiE6__lock, %eax
#APP
	xchgl %eax,_ZZ18__exchange_and_addPViiE6__lock
#NO_APP
	testl	%eax, %eax
	jne	.L2
	movl	(%edx), %eax
	movl	(%edx), %eax
	addl	$10, %eax
	movl	%eax, (%edx)
	popl	%ebp
	movl	$0, _ZZ18__exchange_and_addPViiE6__lock
	ret

If I understand the C code correctly, it tries to put the value 1 into
__lock, and then tries to get 0 out of it. If you get the 0, you hold
the spinlock.

In the assembler code, I see none of this: no 1, but instead it looks
like the value of __lock gets swapped with itself. Apparently, the
declaration of input registers went wrong, it probably should be

   "0" (__tmp)

instead.

If that part is corrected, it seems to me that the answer to the
question "Why is this OK?" is straight forward: We are holding the
lock, so we can release it by just assigning to it. It *may* be
necessary to put the 0 back in using an xchgl as well, but it appears
to me that this should happen atomically anyway - can a memory write
ever be partial on that architecture? Can it if the target address is
aligned?

I'm not quite sure what problem this is going to solve, though, for
Debian: There is an ABI change where, on i386, one needs to hold
__lock to perform the atomic add. This poses two questions

1. Where is __lock expected to live? Currently, it gets into all
   object files, so it would always be present. Due to the nature
   of symbol resolution, you might end up with multiple copies of
   __lock, though, under obscure circumstances.

   If it is supposed to live in libstdc++: How would binaries built
   against this version of the ABI run on installations that assume
   486+? where the variable is not present in libstdc++?

2. What happens if you mix i386 and i486+ ABI in a single program?  It
   appears to me that the following sequence of actions might be
   possible, if two threads simultaneously try to modify the same
   _Atomic_word, one with the i386 ABI, and one with the i486 ABI:
   a) i386 obtains __lock
   b) i386 reads value of __mem into __result
   c) i386 reads value of __mem for addition
   d) i486 performs atomic addition, giving __mem+486
   e) i386 performs addition, and writes back __mem+386
   f) i386 releases __lock
   g) both return __mem
   As a result, the variable is now __mem+386, whereas it should
   be __mem+386+486, so the write operation of i486 was lost.

Regards,
Martin



More information about the Libstdc++ mailing list