Floating point exception take place where they shouldn't when running with KSE threads (-pthread). How-To-Repeat: # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # fpu # fpu/Makefile # fpu/fpu5.c # echo c - fpu mkdir -p fpu > /dev/null 2>&1 echo x - fpu/Makefile sed 's/^X//' >fpu/Makefile << 'END-of-fpu/Makefile' Xall: fpu5 fpu5th X Xfpu5th: fpu5.c X cc -O3 -Wall -W -Werror -g -Wcast-qual -DWITH_THR -fstrict-aliasing -pthread fpu5.c -o fpu5th -lm X Xfpu5: fpu5.c X cc -O3 -Wall -W -Werror -g -Wcast-qual -fstrict-aliasing fpu5.c -o fpu5 -lm X Xclean: X rm -f fpu5 fpu5th fpu5th.core core END-of-fpu/Makefile echo x - fpu/fpu5.c sed 's/^X//' >fpu/fpu5.c << 'END-of-fpu/fpu5.c' X/* Blame it in Marc Olzheim (Zlo) */ X X#ifdef WITH_THR X#include <pthread.h> X#endif /* WITH_THR */ X X#include <err.h> X#include <math.h> X#include <stdio.h> X#include <stdlib.h> X#include <sysexits.h> X#include <unistd.h> X Xvoid * Xcalc_thread(void *arg) X{ X long i; X unsigned char c; X X i = (long)arg + 1; X X for (;;) X { X i = (i + 1) % 736; X if (i > 0) X { X /* ln(2.0) =~ 0.69 */ X if (logf((float)1.0 + (float)i) < (float)0.65) X { X /* Never happens */ X printf("\n\n\n\ni: %ld\n\n\n\n", i); X fflush(NULL); X } X X /* Then why does _this_ go wrong ? */ X c = floorf((float)(1.0 / logf((float)1.0 + (float)i))); X X if (c > 1) /* Never true, just to use c. */ X printf("\r%hhu", c); X } X } X X /* NOTREACHED */ X return NULL; X} X Xint Xmain(int argc, char *argv[]) X{ X#ifdef WITH_THR X pthread_t thread; X#endif /* WITH_THR */ X X if (1 != argc) X { X fprintf(stderr, "Usage: %s\n", argv[0]); X return(EX_USAGE); X } X X#ifdef WITH_THR X if (pthread_create(&thread , NULL, calc_thread, (void *)1L)) X err(1, "pthread_create()"); X#else /* ! WITH_THR */ X (void)calc_thread((void *)1L); X#endif /* ! WITH_THR */ X X for (;;) X sleep(60); X X return(EX_OK); X} END-of-fpu/fpu5.c exit Just compare the th version with the non-th version. The th version will crash. This happens on 6-CURRENT and on 5.4-STABLE and I've only been able to reproduce it on i386, not on amd64. I don't have other test machines atm. 5.3-RELEASE seems unaffected.
It seems to have to do something with floorf(). Leaving it out, I can't get it to crash atm.
floorf() and ceilf() are the only functions where this happens. When replacing the code with doubles and using floor() and ceil() no problems arise. Both floorf() and ceilf() crash in "flds 0x8(%ebp)".
The following probably fixes it (thanks to the hint das@ provided). For FreeBSD 5.4, just ignore the truncf() part, since that file hasn't been MFC'd yet. --- lib/msun/i387/s_ceilf.S Thu Jan 13 19:58:25 2005 +++ lib/msun/i387/s_ceilf.S Thu May 5 00:54:18 2005 @@ -13,17 +13,17 @@ movl %esp,%ebp subl $8,%esp - fstcw -12(%ebp) /* store fpu control word */ - movw -12(%ebp),%dx + fstcw -4(%ebp) /* store fpu control word */ + movw -4(%ebp),%dx orw $0x0800,%dx /* round towards +oo */ andw $0xfbff,%dx - movw %dx,-16(%ebp) - fldcw -16(%ebp) /* load modfied control word */ + movw %dx,-8(%ebp) + fldcw -8(%ebp) /* load modfied control word */ flds 8(%ebp); /* round */ frndint - fldcw -12(%ebp) /* restore original control word */ + fldcw -4(%ebp) /* restore original control word */ leave ret --- lib/msun/i387/s_floorf.S Thu Jan 13 19:58:25 2005 +++ lib/msun/i387/s_floorf.S Thu May 5 00:54:29 2005 @@ -13,17 +13,17 @@ movl %esp,%ebp subl $8,%esp - fstcw -12(%ebp) /* store fpu control word */ - movw -12(%ebp),%dx + fstcw -4(%ebp) /* store fpu control word */ + movw -4(%ebp),%dx orw $0x0400,%dx /* round towards -oo */ andw $0xf7ff,%dx - movw %dx,-16(%ebp) - fldcw -16(%ebp) /* load modfied control word */ + movw %dx,-8(%ebp) + fldcw -8(%ebp) /* load modfied control word */ flds 8(%ebp); /* round */ frndint - fldcw -12(%ebp) /* restore original control word */ + fldcw -4(%ebp) /* restore original control word */ leave ret --- lib/msun/i387/s_truncf.S Sat Apr 16 23:12:55 2005 +++ lib/msun/i387/s_truncf.S Thu May 5 00:54:35 2005 @@ -11,16 +11,16 @@ movl %esp,%ebp subl $8,%esp - fstcw -12(%ebp) /* store fpu control word */ - movw -12(%ebp),%dx + fstcw -4(%ebp) /* store fpu control word */ + movw -4(%ebp),%dx orw $0x0c00,%dx /* round towards -oo */ - movw %dx,-16(%ebp) - fldcw -16(%ebp) /* load modfied control word */ + movw %dx,-8(%ebp) + fldcw -8(%ebp) /* load modfied control word */ flds 8(%ebp) /* round */ frndint - fldcw -12(%ebp) /* restore original control word */ + fldcw -4(%ebp) /* restore original control word */ leave ret
State Changed From-To: open->closed The problem was in libm (src/lib/msun) and fix was committed in -current.
Could this be MFC'd, please, pretty please, with sugar on top ?