[py-dev] error building greenlets

Alain Poirier alain.poirier at net-ng.com
Sun Aug 28 15:08:56 CEST 2005


Hi Armin,

> On Wed, Aug 24, 2005 at 11:31:57PM +0200, Alain Poirier wrote:
> > A code compiled with the -fPIC option must preserve the ebx register.
>
> Indeed.
>
> > So, if it's noted as "clobbered", the new versions of gcc emit an error.
>
> This implication is not clear to me.  The goal of the "clobbered" is
> precisely to force gcc to save the register to the stack and restore it.
> The fact that newer versions of gcc doesn't like 'ebx' in the clobbered
> list any more is an annoyance.

From the gcc doc (and the tests I did), I understand that the clobbered
list only indicate to the compiler what registers are used into the 
function, but not to save them.

http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#ss5.3

> > A 'push ebx' / 'pop ebx' pair need to be added into the slp_switch
> > function of switch_x86_unix.h
>
> Can you show the precise patch?  I guess that you have in mind a "push
> ebx" in the first __asm__ line, and a "pop ebx" in the last one.

Yes

> This might be doing the trick but it looks very fragile (i.e. depending on
> the exact way gcc generates code).

In theorie, we need to save "ebx" which is a bit annoying because the C 
macro SLP_SAVE_STATE do some 'return' and, in these cases, as ebx is not 
popped => crash.

So we could change the 'return' by a 'goto end, in greenlet.c :

#define SLP_SAVE_STATE(stackref, stsizediff)            \
  stackref += STACK_MAGIC;                              \
  if (slp_save_state((char*)stackref)) { r = -1; goto end; }    \
  if (!PyGreen_ACTIVE(ts_target)) { r = 1; goto end; }          \
  stsizediff = ts_target->stack_start - (char*)stackref

In switch_x86_unix.h (and 'end: ...' needed for all the other 
architectures :( :

static int
slp_switch(void)
{
    register int *stackref, stsizediff;
    int r;

    __asm__ volatile ("" : : : "esi", "edi");
    __asm__ ("push %ebx");

    __asm__ ("movl %%esp, %0" : "=g" (stackref));
    {
        SLP_SAVE_STATE(stackref, stsizediff);
        __asm__ volatile (
            "addl %0, %%esp\n"
            "addl %0, %%ebp\n"
            :
            : "r" (stsizediff)
            );
        SLP_RESTORE_STATE();

        r = 0;
    }
end:
    __asm__ ("pop %ebx");
    return r;
    __asm__ volatile ("" : : : "esi", "edi");
}

But,

> Now, I don't expect the value of the PIC register "ebx" to actually
> change during the program execution, so that it will have the same value
> in all greenlets at any time.  If so, we don't actually have to save and
> restore it.  Just removing the "ebx" in the two clobbered lists should
> be enough.

Right. As the "ebx" register is not modified by the asm of slp_switch, it
stays constant. So, in practice, remove "ebx" from the clobbered list is
enough and the simplest solution :)

> This is the conclusion to which I came some time ago already, but the
> problem with it is to detect if the code is indeed being compiled with
> -fPIC or not.  If not, the "ebx" in the clobbered is essential.  Any
> clue?

Hmm, I don't see why "ebx" in the clobbered is essential for a code compiled 
without -fPIC ?

Amicalement,

Alain




More information about the Pytest-dev mailing list