On Sat, Mar 01, 2003 at 10:57:51PM +0200, Jarkko Hietaniemi wrote: > Here's an attempt to squash the glibc _moddi3 negative quad bug that's > been around for aeons. An aeon. Almost a year. (The bug is also > known as [perl #9402] or "Abigail's faithfully failing int.t".) > I didn't feel like writing a Configure test for such a precise bug > but instead went for runtime. Now pp_i_modulo is basically a switchboard > that rewires the opcode dispatch table as required (thus effectively > rewiring itself out of the way). The patch works for me-- I've got > the same buggy glibc in the Debian box I run my smokes in. > Nice hack, however don't you also want to replace PL_op->op_ppaddr so that the next time this OP executes it will use the direct version, since the PL_peepaddr is only used for new ops since runops does while ((PL_op = CALL_FPTR(PL_op->op_ppaddr)(aTHX))) { > --- pp.c.orig 2003-03-01 22:51:50.000000000 +0200 > +++ pp.c 2003-03-01 22:51:55.000000000 +0200 > @@ -2457,6 +2457,40 @@ > } > } > > +STATIC > +PP(pp_i_modulo_0) > +{ > + /* This is the vanilla old i_modulo. */ > + dSP; dATARGET; tryAMAGICbin(modulo,opASSIGN); > + { > + dPOPTOPiirl; > + if (!right) > + DIE(aTHX_ "Illegal modulus zero"); > + SETi( left % right ); > + RETURN; > + } > +} > + > +STATIC > +PP(pp_i_modulo_1) > +{ > +#ifdef __GLIBC__ > + /* This is the i_modulo with the workaround for the _moddi3 > + * bug in (at least) glibc 2.2.5 (the "right = -right" part > + * is the workaround). See below for pp_i_modulo. */ > + dSP; dATARGET; tryAMAGICbin(modulo,opASSIGN); > + { > + dPOPTOPiirl; > + if (!right) > + DIE(aTHX_ "Illegal modulus zero"); > + if (right < 0) > + right = -right; > + SETi( left % right ); > + RETURN; > + } > +#endif > +} > + > PP(pp_i_modulo) > { > dSP; dATARGET; tryAMAGICbin(modulo,opASSIGN); > @@ -2464,6 +2498,28 @@ > dPOPTOPiirl; > if (!right) > DIE(aTHX_ "Illegal modulus zero"); > + /* The assumption is to use hereafter the old vanilla version... */ > + PL_ppaddr[OP_I_MODULO] = &Perl_pp_i_modulo_0; + PL_op->op_ppaddr = &Perl_pp_i_modulo_0; > + /* .. but if we have glibc, we might have a buggy _moddi3 > + * (at least glicb 2.2.5 is known to have this bug), in other > + * words our integer modulus with negative quad as the second > + * argument might be broken. Test for this and re-patch the > + * opcode dispatch table if that is the case, remembering to > + * also apply the workaround so that this first round works > + * right, too. > + * > + * See [perl #9402] for more information. */ > +#if defined(__GLIBC__) && IVSIZE == 8 > + { > + IV l = 3; > + IV r = -10; > + if (l % r == -3) { > + PL_ppaddr[OP_I_MODULO] = &Perl_pp_i_modulo_1; PL_op->op_ppaddr = &Perl_pp_i_modulo_1; > + if (right < 0) > + right = -right; > + } > + } > +#endif > SETi( left % right ); > RETURN; > } > > -- > Jarkko Hietaniemi <jhi@iki.fi> http://www.iki.fi/jhi/ "There is this special > biologist word we use for 'stable'. It is 'dead'." -- Jack Cohen Yes this is threadsafe. ArthurThread Previous | Thread Next